2013-07-10 68 views
2

好吧,這是一個很奇怪的問題。哈斯克爾正弦和餘弦函數不起作用

內置的Haskell正弦函數(sin)似乎不起作用。

sin 0正確地給出0

sin pi給出,無論出於何種原因,1.2246467991473532e-16

這些是使用內置的前奏功能。我只是啓動ghci(Haskell解釋器),然後輸入sin pi並得到錯誤的答案。

此外,cos (pi/2)6.123233995736766e-17

任何想法,這可能是爲什麼?它看起來像函數中的構建是完全錯誤的......這看起來不太可能看到Haskell標準庫的數學導向。

編輯:嘿,我只是簡單地忽略了電子16 ..我想這就是我在深夜編碼得到的。無論如何每個人都謝謝

+0

也許你應該試試'1 + sin pi',這樣你可以看到它實際上離正確的答案有多近。 – augustss

+1

您也可以安裝數字包,並使用類型'Data.Number.CReal.CReal'而不是'Double'。它速度慢,準確。 – augustss

回答

18

這是Matlab的

>> sin(pi) 
ans = 
    1.2246e-016 

下面是Python的

>>> from math import sin, pi 
>>> sin(pi) 
1.2246467991473532e-16 

您正在運行到的浮點精度的限制。我建議閱讀What Every Computer Scientist Should Know About Floating Point Arithmetic


e在這些數字的結束表明,他們在(的一種緊湊的形式)scientific notation,和代表「×10 ^」。例如,在此表示法中,2e3對應於2×10 = 2000。這裏,您有一個數字乘以10很小的數字,即10 -16。全部寫出來,1.2246467991473532e-16 = 0.00000000000000012246467991473532,所以誤差量非常小。


如果你想在Haskell準確的實數計算,你可以按如下方式使用CReal包。

>>> import Data.Number.CReal 
>>> sin (0.0 :: CReal) 
0.0 
>>> sin (pi :: CReal) 
0.0 
>>> cos (pi/2 :: CReal) 
0.0 

這工作,因爲一個CReal「引擎蓋下」是一個功能Int -> Integer。給定要輸出的若干位數d,該函數產生Integer,除以10^d時,該值將給出實際的小數位數爲d的小數位數。

+0

這裏真正的問題是「pi」本身。 – devnull

+0

我瞭解浮點精度,它只是沒有發生在我身上,因爲1.2離0很遠。你知道,在數學上,這個錯誤有多合理嗎? – Nathan

+4

@Nathan結果是'1.22 * 10 ^( - 16)',它(相對而言)非常接近零 - 它大致爲'0.000000000000000122'。 –

2

雙精度pi本身的錯誤是-2.3846200000000026e-17,所以在像sin這樣的函數中丟失另一個小數的精度並不差。