【问题标题】:Why do floating point operations display different in some languages?为什么浮点运算在某些语言中显示不同?
【发布时间】:2014-11-27 22:05:51
【问题描述】:

我已经阅读了这些:

他们解释“如何”。我想知道为什么这些语言会有所不同。在相同输入的情况下,我希望得到类似的结果。

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

【问题讨论】:

  • 也许不同的语言都得到相同的答案,但它们显示它的方式不同。例如,您可以使用 decimal 模块在 Python 中获得更高的打印精度。 import decimal; print decimal.Decimal(9.0 * 0.001)0.009000000000000001054711873393898713402450084686279296875
  • 由于您实际上并没有测试任何值是否 equal 特别是,您的问题真的是关于为什么 representations i> 有什么不同?
  • 默认看起来像 C/C+ prints 6 significant digits.
  • @rgettman:这 6 个小数位在 C 中得到保证,在 C++ 中通过引用来保证。
  • 这里的元评论:有没有人认为这里有floating-pointfloating-point-precision 标签比所有5 种语言都更有用?我正在努力思考是什么让它出现在搜索结果中。

标签: floating-point


【解决方案1】:

在我的系统上的 C 中:

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

0.009000000000000001

在我系统上的 Python 中:

print("%.18f" % result)

0.009000000000000001

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

【讨论】:

    【解决方案2】:

    @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”。实际上,它会搜索所有等效的字符串表示形式(使用相同的底层浮点值存储的字符串表示形式)并返回最短的表示形式。

    【讨论】:

    • 您写道“除了 C 和 Python 之外的所有语言都只是将浮点值打印到尽可能多的小数位”,但事实并非如此。例如,Java 和 Javascript 会根据需要打印出尽可能多的小数位,以将这个特定的双精度数字与两边的数字区分开来。我不是 Ruby 方面的专家,但它似乎在做同样的事情。当然,根据凯文在问题下的评论,这些语言中的任何一种都可以打印出更多的小数位。
    • Python 的行为非常奇怪......而且很有趣。我想把它作为一个可用的工具,虽然不是默认的。
    • @MooingDuck:Python 的行为并没有那么不寻常:Java 的 Double.toString 基本上做同样的事情,而 Tcl 和(我相信)Ruby >= 1.9 都做了类似的事情。
    • @MarkDickinson +1,还添加了 scheme、Squeak 和 Pharo Smalltalk 等。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多