2014-10-02 78 views
18

我已閱讀這些:爲什麼浮點運算在某些語言中顯示不同?

他們解釋 「如何」。我想知道爲什麼它在這些語言中有所不同。考慮到相同的投入,我期望得到類似的結果

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

+19

也許不同的語言都會得到相同的答案,但是它們顯示的方式是不同的。例如,你可以使用'decimal'模塊在Python中獲得更多的打印準確性。 '進口小數;打印decimal.Decimal(9.0 * 0.001)'給出'0.009000000000000001054711873393898713402450084686279296875'。 – Kevin 2014-10-02 20:20:19

+2

由於您實際上並沒有測試任何值是否等於任何特定值,因此您的問題實際上是爲什麼*表示法不同? – DSM 2014-10-02 20:20:43

+3

默認情況下它看起來像C/C + [打印6位有效數字](http://stackoverflow.com/questions/20135901/c-cout-double-not-printing-decimal-places)。 – rgettman 2014-10-02 20:21:38

回答

15

@ouah確定語言的行爲都一樣。我的答案旨在解釋爲什麼他們顯得不同。只有兩種具有「不同」輸出的語言是C和Python。

顯然,除C和Python以外的每種語言都只是將float值打印到儘可能多的小數位。

C很容易解釋。您使用printf("%f", result),而不指定明確的精度值。根據C標準,f說明符的精度默認爲6.因此,打印出精確的六位小數位,這就是您所看到的。正如@ouah指出的那樣,將精度設置爲18將產生「預期」輸出。這是有損的:在小數點後第七位打印出來的雙打將以相同的方式打印出來,因此不能依靠%f的輸出精確重建原始浮標。

Python有點棘手。基於David Gay的工作,Python 3.1引入了一個新的浮點數repr算法。與該功能對應的Python問題在這裏:http://bugs.python.org/issue1580。該功能也被反向移植到了Python 2.7。

這個新功能的目的是爲了減少對浮點的混淆(儘管這很可疑),更重要的是提供更多的人類可讀的,更短的浮點數表示而不影響往返行爲 ;即float(repr(x))總是等於x,即使repr(x)由於此算法而縮短。因此,該算法設法產生較短的浮點表示,同時保持「無損」:雙贏!

官方介紹說,這多少:

的再版(1.1)新算法是更聰明,並返回 '1.1'。實際上,它會搜索所有等價的字符串表示(存儲具有相同基礎浮點值的字符串表示)並返回最短表示。

+2

您寫過「除C和Python以外的每種語言都只是將float值打印到儘可能多的小數位」,但事實並非如此。例如,Java和Javascript會根據需要輸出儘可能多的小數位數,以區分這種特定的雙精度數字與任何一方。我不是Ruby的專家,但它似乎也在做同樣的事情。當然,這些語言中的任何一種都可以打印出更多的小數位 - 正如凱文在該問題下的評論。 – 2014-10-03 00:31:20

+0

Python的行爲非常奇怪......並且很有趣。我希望將它作爲可用的工具,但不是默認的。 – 2014-10-03 00:35:17

+1

@MooingDuck:Python的行爲並不是那麼不尋常:Java的'Double.toString'本質上是一樣的,而且Tcl和(我相信)Ruby> = 1.9都做了類似的事情。 – 2014-10-03 15:53:45

17

在C我的系統上:

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

0.009000000000000001 

在Python我的系統上:

print("%.18f" % result) 

0.009000000000000001 

與其他語言一樣,C或Python默認使用其打印函數限制小數位數。