Doubles in IEE754 have a precision of 52 bits which means they can store numbers accurately up to (at least) 251.
IEE754中的双精度具有52位的精度,这意味着它们可以准确地存储数字(至少)251。
If your longs are 32-bit, they will only have the (positive) range 0 to 231 so there is no 32-bit long that cannot be represented exactly as a double. For a 64-bit long, it will be (roughly) 252 so I'd be starting around there, not at zero.
如果你的long是32位,它们只有(正)范围0到231,所以没有32位长,不能完全表示为double。对于64位长,它将(大致)252,所以我将在那里开始,而不是零。
You can use the following program to detect where the failures start to occur. An earlier version I had relied on the fact that the last digit in a number that continuously doubles follows the sequence {2,4,8,6}. However, I opted eventually to use a known trusted tool (bc)
for checking the whole number, not just the last digit.
您可以使用以下程序来检测故障开始的位置。我之前的版本依赖于这样一个事实:数字中的最后一个数字连续加倍,遵循序列{2,4,8,6}。但是,我最终选择使用已知的可信工具(bc)来检查整数,而不仅仅是最后一位数。
Keep in mind that this may be affected by the actions of sprintf()
rather than the real accuracy of doubles (I don't think so personally since it had no troubles with certain numbers up to 2143).
请记住,这可能会受到sprintf()的操作的影响,而不是双打的真实准确性(我不这么认为,因为它对2143年的某些数字没有任何麻烦)。
This is the program:
这是该计划:
#include
#include
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++;
}
}
This keeps going until:
这一直持续到:
2^51 - 1 = 2251799813685247
2^52 - 1 = 4503599627370495
2^53 - 1 = 9007199254740991
2^54 - 1 <-- bc failure
got [18014398509481984]
expected [18014398509481983]
which is about where I expected it to fail.
这是关于我预期失败的地方。
As an aside, I originally used numbers of the form 2n but that got me up to:
顺便说一句,我最初使用2n形式的数字,但这让我达到了:
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]
with the size of a double being 8 bytes (checked with sizeof
). It turned out these numbers were of the binary form "1000..."
which can be represented for far longer with doubles. That's when I switched to using 2n-1 to get a better bit pattern: all one bits.
double的大小是8个字节(用sizeof检查)。事实证明,这些数字是二进制形式“1000 ......”,可以用双倍表示更长的时间。那是当我切换到使用2n-1来获得更好的位模式时:所有的一位。