Учет двойных чисел в IEE754 составляет 52 бита, что означает, что они могут точно хранить цифры до (по крайней мере) 2 .
Если ваши длинны 32-разрядные, они будут иметь только (положительный) диапазон от 0 до 2 , поэтому нет 32-битного длинного изображения, которое невозможно представить точно как двойное. Для 64-битной длины это будет (примерно) 2 , поэтому я бы начал там, а не в нуле.
Вы можете использовать следующую программу, чтобы определить, где возникают сбои. В более ранней версии я полагался на то, что последняя цифра в числе, которая непрерывно удваивается, следует последовательности {2,4,8,6}. Тем не менее, я решил в конечном итоге использовать известный доверенный инструмент (bc)
для проверки всего числа, а не только последней цифры.
Имейте в виду, что это может быть затронуты действиями sprintf()
, а не реальную точность удваивается (я не думаю, что так лично, так как у него не было никаких проблем с определенными номерами до 2).
Это программа:
#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++;
}
}
Это продолжает идти до:
2^51 - 1 = 2251799813685247
2^52 - 1 = 4503599627370495
2^53 - 1 = 9007199254740991
2^54 - 1 <-- bc failure
got [18014398509481984]
expected [18014398509481983]
, который о том, где я ожидал, что он не в состоянии.
Как и в сторону, я первоначально использовались чисел вида 2 п но у меня до:
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]
с размером двойным будучи 8 байт (проверено с sizeof
). Оказалось, что эти числа имеют двоичную форму "1000..."
, которая может быть представлена длиннее с удвоениями. Вот когда я переключился на использование 2 n -1, чтобы получить лучший бит: все бит.
Вышеприведенный код, по-видимому, охватывает все целые числа. Вместо этого я бы рассмотрел бинарный поиск. Он должен сходиться с 53 или около того итераций, а не 2^53. –
Двоичный поиск без какого-либо априорного знания представлений не сработает. ** Все ** полномочия из двух представляются точно так же, как двойные, поэтому, если ваш бинарный поиск прошел две степени, он мог бы полностью пропустить поиск нужной точки ... :-) –
Возможный дубликат [Который является первым целым числом что плавающий IEEE 754 не может точно представлять?] (http://stackoverflow.com/questions/3793838/which-is-the-first-integer-that-an-ieee-754-float-is-incapable-of -представитель-е) –