2011-08-07 37 views
11

Python version | Javascript version | WhitepaperPython vs Javascript浮點運算給出了非常不同的答案。我究竟做錯了什麼?

因此,我正在一個網站上計算兩個玩家遊戲的Glicko評分。它涉及到大量的浮點運算(平方根,指數,除法,所有討厭的東西),而且出於某種原因,我正在從線程換行算法的Python實現中獲得完全不同的答案。 Python版本基本上爲原始白皮書中描述該算法的示例提供了預期的答案,但是Javascript版本相對較差。

我在翻譯過程中犯了一個錯誤還是Javascript的浮點數學不太準確?

Expected answer: [1464, 151.4] 
Python answer: [1462, 155.5] 
Javascript answer: [1470.8, 89.7] 

所以評級計算不是很差,準確率爲99.6%,但方差已經減少了2/3!

編輯:人們已經指出,Pyglicko版本中RD的默認值是200.這是原始實現者留在測試代碼中的一種情況,我相信,因爲測試用例是用RD 200,但顯然默認應該是350.但是,我確實在Javascript中指定了200個測試用例,所以這不是問題。

編輯:更改算法以使用map/reduce。評級不太準確,差異更準確,無論是否有明顯的原因。 Wallbanging開始。

+1

這可能是因爲Python和JavaScript不以相同的方式處理浮點數。你知道浮點數的工作原理嗎?(當他們沒有) – Halcyon

+2

不知道這是否有任何意義,但rd在python中默認爲200,在javascript中默認爲350。 @Frits:兩者都使用IEEE 754. –

+0

是的,我瞭解浮點數的工作方式,例如,它們不能精確地表示十進制數。 @Daniel Baulig:RD在Python中默認爲200,這是不正確的,但用於測試用例。在白皮書中,它指定RD默認爲350,但給出的測試用例在RD爲200的玩家上 - 所以我在Javascript中設置了正確的默認值,但在RD爲200的測試用例中稱爲新玩家 –

回答

7

通常你會得到類似這樣的錯誤,在這種情況下,你正在減去兩個相似的數字 - 那麼這兩個值之間的正常無關緊要的差異就會被放大。例如,如果python中有兩個值1.2345和1.2346,但javascript中的值爲1.2344和1.2347,則差異分別爲1e-4和3 e-4(即一個是另一個的3倍)。

所以我會看看你在代碼中的減法,並檢查這些值。你可能會發現你可以(1)重寫數學以避免減法(通常情況下,你可以找到一個表達式來計算差異)或者(2)關注爲什麼這個特定點的值兩種語言不同(可能是pi的區別,其他答案是以這種方式被放大)。

雖然這裏不太可能,但也有可能存在差異,因爲某些東西在python中被視爲整數,而在javascript中則被視爲float。在Python中,整數和浮點數是有區別的,如果你不小心,你可以像分割兩個整數一樣獲得另一個整數(例如Python中的3/2 = 1)。而在JavaScript中,所有數字都是「真正的」浮動,所以這不會發生。

最後,在計算方式上可能會有細微的差異。但這些都是「正常的」 - 爲了得到如此激烈的差異,你需要像上面描述的那樣發生。 PS:還請注意Daniel Baulig在上述註釋中對參數rd的初始值所說的內容。

+0

由於這兩種語言都使用IEEE 754作爲它們的浮點實現,所以我沒有看到相同的輸入如何在兩個系統上產生兩個不同的數字。我非常確定,所有的東西都指出了一些非常重要的東西。在JavaScript代碼中,PI僅被粗略地描述,而在Python代碼中則使用了Math常量。這將導致錯誤的結果。 –

+1

有兩個單獨的問題。存在完全重複結果的問題,但也關於以穩定的方式實施計算。如果你得到的結果會根據你在PI中有多少有效數字而大幅變化,那就表明整個系統都是病態的。可能是通過強迫PI完全相等,原始提問者在兩種情況下都可以得到相同的結果,但他仍然會有可疑的代碼。另一方面,如果他更好地理解不穩定因素,他實際上可以改善他所擁有的東西。 –

+1

ieee也不完美。請參閱http://en.wikipedia.org/wiki/IEEE_754-2008#Reproducibility上的評論 - 我不知道與完美實現有多接近,或者它們是否使用相同的庫,但期望在相同的庫上有相同的結果投入有點樂觀。 –

2

我的猜測是涉及到JavaScript版本中某些常量的近似值。你的pi2特別看起來有點簡單。我相信Python對這些值使用雙打。

+0

我在使用Math.PI^2的node.js中嘗試了他的代碼 - 仍然得到了1470.8 – Alnitak

+0

我原來對所有常量都有Math.whatever,並且在故障排除過程中用實際用於計算的常量值替換它們在白皮書中(一般有5位有效數字)。 –