2013-07-10 70 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这样的函数中丢失另一个小数的精度并不差。