为什么我需要17位有效数字(而不是16位)才能代表双倍数字?

有人能给我一个浮点数(双精度)的例子,需要超过16位有效十进制数来表示它吗?

我在这个post中发现有时候你需要多达17位,但是我找不到这样一个数字的例子(16对我来说似乎足够了)。

有人可以澄清一下吗?

非常感谢!

我的另一个答案是错误的。

#include  int main(int argc, char *argv[]) { unsigned long long n = 1ULL << 53; unsigned long long a = 2*(n-1); unsigned long long b = 2*(n-2); printf("%llu\n%llu\n%d\n", a, b, (double)a == (double)b); return 0; } 

编译并运行以查看:

 18014398509481982 18014398509481980 0 

a和b只是2 *(2 ^ 53-1)和2 *(2 ^ 53-2)。

这些是17位数的基数为10的数字。 四舍五入到16位时,它们是相同的。 然而a和b显然只需要53位精度来表示base-2。 因此,如果你拿a和b并将它们加倍,你得到反例。

我认为那个线程上的那个人是错的,16个base-10数字总是足以代表IEEE的两倍。

我对证据的尝试将是这样的:

另外假设。 然后,必然地,两个不同的双精度数必须由相同的16位有效数字的基数10表示。

但是两个不同的双精度数必须相差2 ^ 53中的至少一个部分,其大于10 ^ 16中的一个部分。 并且没有两个数字相差10 ^ 16中的多个部分可能会转向相同的16位有效数字的基数为10的数字。

这不是完全严格的,可能是错的。 🙂

正确答案是Nemo上面的答案。 在这里,我只是粘贴一个简单的Fortran程序,显示两个数字的示例,需要17位数的精度进行打印,显示,如果一个人不想要,则需要(es23.16)格式来打印双精度数字松散任何精度:

 program test implicit none integer, parameter :: dp = kind(0.d0) real(dp) :: a, b a = 1.8014398509481982e+16_dp b = 1.8014398509481980e+16_dp print *, "First we show, that we have two different 'a' and 'b':" print *, "a == b:", a == b, "ab:", ab print *, "using (es22.15)" print "(es22.15)", a print "(es22.15)", b print *, "using (es23.16)" print "(es23.16)", a print "(es23.16)", b end program 

它打印:

 First we show, that we have two different 'a' and 'b': a == b: F ab: 2.0000000000000000 using (es22.15) 1.801439850948198E+16 1.801439850948198E+16 using (es23.16) 1.8014398509481982E+16 1.8014398509481980E+16 

深入研究单精度和双精度基础知识,并断言这个或那个(16-17)很多DECIMAL数字的概念并开始考虑(53)BINARY数字。 如果你花一些时间挖掘,可以在stackoverflow找到必要的例子。

而且我没有看到如何在没有合格的BINARY解释的情况下给予DECIMAL答案的人给出最佳答案。 这个东西很简单,但并不简单。

可以用双精度(8字节IEEE)精确表示的最大连续整数范围是-2 ^ 53到2 ^ 53(-9007199254740992。到9007199254740992)。 数字-2 ^ 53-1和2 ^ 53 + 1不能用double精确表示。

因此,小数点左边不超过16位有效十进制数字将精确表示连续范围内的两倍。