小数点后双精度浮点数的精度

7
在午休时,我们开始辩论关于double值类型的精度问题。
我的同事认为它总是有15个小数点后面的位数。
在我看来,这是无法确定的,因为IEEE 754并不作出假设,这取决于二进制表示中第一个1的位置。(即小数点前数字的大小也很重要)
如何才能作出更有资格的陈述呢?

你是按绝对值还是按科学计数法推理?你会如何考虑像0.001e5这样的数字? - Nicola Musatti
我们正谈论这个问题。我的同事坚持要在小数点后保留15位。我的观点是,你需要一个53位的尾数来表示所有的位数。但是好像很难以合格的方式解释清楚这个问题。 - Mare Infinitus
只是为了更清楚:这特别是一个C#问题。如果内部C#表示不是IEEE 754,而是小数点后15位,那就非常有趣。 - Mare Infinitus
C#中的双精度数的内部表示确实是IEEE 754,或者更确切地说是相应的国际标准IEC 60559。 - Nicola Musatti
4个回答

5
根据C#参考文献所述,精度在小数点前后取决于所表示的小数值,为15到16位数字。
简而言之,您是正确的,它取决于小数点前后的值。
例如:
12345678.1234567D //右侧下一个数字将被四舍五入 1234567.12345678D //右侧下一个数字将被四舍五入
完整示例请参见: http://ideone.com/eXvz3 此外,试图将double值视为固定的十进制值并不是一个好主意。

4
只是指出一下,这意味着总共有15位数字,而不仅仅是小数点后的位数。 - Joachim Isaksson

2

你们两个都错了。一个常规的double有53个位数的精度。这大约相当于16个小数位,但把double值看作十进制数会导致很多混淆,最好避免。

话虽如此,你比你的同事接近正确——精度是相对于所表示的值而言的;足够大的double没有任何小数位的精度。

例如,比4503599627370496.0稍大的下一个double4503599627370497.0


0

C# 中的 double 类型使用 IEEE 754 标准进行表示,其中包含一个 53 位有效数字 p(又称尾数)和一个 11 位指数 e,其范围在 -1022 到 1023 之间。因此,它们的取值范围为

p * 2^e

尾数总是在小数点前有一位数字,因此其小数部分的精度固定。另一方面,在浮点数中小数点后的数字取决于指数;指数超过尾数小数部分的位数的数字本身就没有小数部分。

计算机科学家应该了解的浮点运算知识可能是这个主题上最广为人知的出版物。


0

由于这是我在SO上能找到唯一关于该主题的问题,因此我想对jorgebg's answer进行补充。

根据这个, 精度实际上是15-17位数字。一个具有17位精度的double示例将是0.92107099070578813(别问我怎么得到这个数字:P)


你是怎么获得这个数字的? - v01pe
1
如果你需要知道...这是由一个测试随机生成的,我正在测试一个函数,该函数将一小段double序列化为ulong。由于我尝试序列化的double值从略小于1.0到略小于10.0,所以我认为将double的值乘以10^16应该会给我一个ulong,然后我可以将其除以10^16来检索原始值。这个数字是调试器显示的第一个无法工作的示例的值。与此同时,我找到了更好的序列化方法。现在你知道了。 - Vlad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接