Floating point 为什么浮点运算在某些语言中显示不同?

Floating point 为什么浮点运算在某些语言中显示不同?,floating-point,Floating Point,我读过: 他们解释“如何”。我想知道为什么这些语言之间有差异。在相同的输入下,我期望得到类似的结果 test.js #!/usr/bin/env node var nine = 9.0; var pointOhOhOne = 0.001; var result = nine * pointOhOhOne; console.log(result); test.java public class test { public static void main(String[] arg

我读过:

他们解释“如何”。我想知道为什么这些语言之间有差异。在相同的输入下,我期望得到类似的结果

test.js

#!/usr/bin/env node

var nine = 9.0;
var pointOhOhOne = 0.001;
var result = nine * pointOhOhOne;
console.log(result);
test.java

public class test {

  public static void main(String[] argv) {
    double nine = 9.0d;
    double pointOhOhOne = 0.001d;
    double result = nine * pointOhOhOne;
    System.out.println(result);
  }

}
测试c

#include "stdio.h"

int main() {
  double nine = 9.0;
  double pointOhOhOne = 0.001;
  double result = nine * pointOhOhOne;
  printf("%f", result);
}
test.rb

#!/usr/bin/env ruby

nine = 9.0
pointOhOhOne = 0.001
result = nine * pointOhOhOne

print result
test.py

#!/usr/bin/env python

nine = 9.0
pointOhOhOne = 0.001
result = nine * pointOhOhOne

print result
结果:

ruby     0.009000000000000001
python   0.009
node     0.009000000000000001
java     0.009000000000000001
c        0.009000
要点:

在我的系统上使用C语言:

printf("%.18f\n", result);

0.009000000000000001
print("%.18f" % result)

0.009000000000000001
在我的系统上的Python中:

printf("%.18f\n", result);

0.009000000000000001
print("%.18f" % result)

0.009000000000000001

与其他语言一样,C或Python在默认情况下通过其打印函数限制小数位数。

@ouah确定这些语言的行为都是相同的。我的回答旨在解释为什么它们看起来不同。仅有的两种具有“不同”输出的语言是C和Python

显然,除了C和Python之外的每种语言都只是将浮点值打印到尽可能多的小数位数

C很容易解释。使用
printf(“%f”,result)
,而不指定显式精度值。根据C标准,
f
说明符的精度默认为6。因此,精确地打印出小数点后六位,这就是您看到的。正如@ouah所指出的,将精度设置为18将产生“预期”输出。这是有损的:超过小数点后第7位的双精度将以相同的方式打印出来,因此不能依赖
%f
的输出来准确地重建原始浮点

Python有点棘手。Python 3.1在David Gay的工作基础上引入了一种新的浮点
repr
算法。与此功能对应的Python问题如下:。这个特性也被后传到了Python2.7中

这一新功能的目的是减少对浮点的混淆(尽管这可能有用),更重要的是,在不影响往返行为的情况下,提供更具可读性、更短的浮点数表示形式;也就是说,
float(repr(x))
始终等于
x
,即使该算法缩短了
repr(x)
。因此,该算法能够在保持“无损”的同时生成更短的浮点表示:双赢

官方的描述说明了这一点:

repr(1.1)的新算法更智能,返回“1.1”。实际上,它搜索所有等价的字符串表示形式(使用相同的基础浮点值存储的字符串表示形式),并返回最短的表示形式


也许不同的语言都会得到相同的答案,但它们显示答案的方式不同。例如,您可以使用
decimal
模块在Python中获得更高的打印精度<代码>导入小数;打印十进制。十进制(9.0*0.001)给出
0.00900000000000000105471187339389871340240084686279296875
。由于实际上不测试任何值是否等于任何特定值,你的问题是为什么陈述不同?它看起来像C/C+默认。@ RGTTMAN:这6个小数点在C中保证,并且在C++中引用。元注释:有人认为这里的标签比所有的5种语言都有用吗?我在想什么会让搜索结果出现这种情况。你写过“除了C和Python之外的每种语言都在尽可能多地打印浮点值”,但事实并非如此。例如,Java和Javascript可以打印出所需的任意多个小数位,以将这个特定的双精度数字与两边的数字区分开来。我不是Ruby方面的专家,但它似乎也在做同样的事情。当然,这些语言中的任何一种都可以打印出更多的小数位——正如Kevin在这个问题下的评论。。。而且很有趣。我想把它作为一个可用的工具,尽管不是默认工具。@MooingDuck:Python的行为并不是那么不寻常:Java的
Double。toString
基本上做了相同的事情,Tcl和(我相信)Ruby>=1.9都做了类似的事情。@MarkDickinson+1,还添加了scheme、Squeak和Pharo Smalltalk等。