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

时间:2014-10-02 20:16:53

标签: 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[] argv) {
    double nine = 9.0d;
    double pointOhOhOne = 0.001d;
    double result = nine * pointOhOhOne;
    System.out.println(result);
  }

}

test.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

要点:https://gist.github.com/reklis/6694ad5fb01991a79a1a

2 个答案:

答案 0 :(得分:17)

在我系统的C中:

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

0.009000000000000001

在我的系统上使用Python:

print("%.18f" % result)

0.009000000000000001

C或Python与其他语言一样,默认情况下使用其打印功能限制小数位数。

答案 1 :(得分:15)

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

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

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

Python有点棘手。 Python 3.1基于David Gay的工作引入了一种新的浮点repr算法。与此功能对应的Python问题在于:http://bugs.python.org/issue1580。此功能也被反向移植到Python 2.7。

这个新功能的目的是减少对浮点的混淆(虽然这有点可疑),更重要的是提供更人性化的,更短的浮点数表示而不影响往返行为;也就是说,float(repr(x))总是等于x,即使由于此算法缩短了repr(x)。因此,算法设法产生更短的浮点表示,同时保持"无损":双赢!

官方说明说了这么多:

  

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