Podwaja w IEE754 mają precyzję 52 bitów, co oznacza, e mogą przechowywać numery dokładnie (co najmniej) 2 .
Jeśli twoje długie są 32-bitowe, będą miały tylko (dodatni) zakres od 0 do 2 , więc nie ma 32-bitowej długości, która nie może być dokładnie odwzorowana jako podwójna. Dla 64-bitowej długości będzie to (w przybliżeniu) 2 , więc zacznę od tego miejsca, nie w punkcie zerowym.
Możesz użyć poniższego programu, aby wykryć, gdzie zaczynają się awarie. Wcześniejsza wersja polegała na tym, że ostatnia cyfra liczby, która stale podwaja się zgodnie z sekwencją {2,4,8,6}. Jednak ostatecznie zdecydowałem się użyć znanego zaufanego narzędzia (bc)
do sprawdzenia całkowitej liczby, a nie tylko ostatniej cyfry.
Należy pamiętać, że ten może być dotknięte działaniami sprintf()
zamiast rzeczywistej dokładności deblu (I nie sądzę osobiście, ponieważ nie miał żadnych kłopotów z określonych numerów do 2).
To jest program:
#include <stdio.h>
#include <string.h>
int main() {
FILE *fin;
double d = 1.0; // 2^n-1 to avoid exact powers of 2.
int i = 1;
char ds[1000];
char tst[1000];
// Loop forever, rely on break to finish.
while (1) {
// Get C version of the double.
sprintf (ds, "%.0f", d);
// Get bc version of the double.
sprintf (tst, "echo '2^%d - 1' | bc >tmpfile", i);
system(tst);
fin = fopen ("tmpfile", "r");
fgets (tst, sizeof (tst), fin);
fclose (fin);
tst[strlen (tst) - 1] = '\0';
// Check them.
if (strcmp (ds, tst) != 0) {
printf("2^%d - 1 <-- bc failure\n", i);
printf(" got [%s]\n", ds);
printf(" expected [%s]\n", tst);
break;
}
// Output for status then move to next.
printf("2^%d - 1 = %s\n", i, ds);
d = (d + 1) * 2 - 1; // Again, 2^n - 1.
i++;
}
}
to leci do:
2^51 - 1 = 2251799813685247
2^52 - 1 = 4503599627370495
2^53 - 1 = 9007199254740991
2^54 - 1 <-- bc failure
got [18014398509481984]
expected [18014398509481983]
która jest o tym, gdzie spodziewałem się, że nie.
Tak na marginesie, ja pierwotnie używane numery od postaci 2 n ale że dostał mi się do:
2^136 = 87112285931760246646623899502532662132736
2^137 = 174224571863520493293247799005065324265472
2^138 = 348449143727040986586495598010130648530944
2^139 = 696898287454081973172991196020261297061888
2^140 = 1393796574908163946345982392040522594123776
2^141 = 2787593149816327892691964784081045188247552
2^142 = 5575186299632655785383929568162090376495104
2^143 <-- bc failure
got [11150372599265311570767859136324180752990210]
expected [11150372599265311570767859136324180752990208]
o rozmiarze podwójnego wynosi 8 bajtów (sprawdzone z sizeof
). Okazało się, że liczby te mają postać binarną "1000..."
, która może być reprezentowana przez daleka znacznie dłużej. Wtedy przełączyłem się na używanie 2 n -1, aby uzyskać lepszy wzór bitowy: wszystkie bity.
Powyższy kod wydaje się przeszukiwać każdą liczbę całkowitą. Zamiast tego rozważałbym wyszukiwanie binarne. Powinien on zbiegać się z 53 lub więcej iteracjami, a nie 2^53. –
Wyszukiwanie binarne bez pewnej wiedzy a priori o reprezentacjach nie działałoby. ** Wszystkie ** moce dwóch są reprezentowalne dokładnie tak samo, jak podwójne, więc jeśli twoje binarne przeszukanie zdarzyło się kroczyć potęgą dwóch, to może zupełnie nie znaleźć szukanego punktu ... :-) –
możliwy duplikat [Która jest pierwszą liczbą całkowitą że pływak IEEE 754 nie jest w stanie dokładnie reprezentować?] (http://stackoverflow.com/questions/3793838/which-is-the-first-integer-that-an-ieee-754-float-is-incapable-of -representing-e) –