sin 函数返回超出范围 [-1, 1] 的数字

sin function returning numbers outside of range [-1, 1]

我在 Haskell 工作,遇到一个错误,对于非常大的浮点数 z,sin(z) returns 一些值超出范围 [-1, 1] .

我是第一次学习 Haskell,所以我在调试时运气很差,当 sin(z) return 的值超出上述范围时,程序就崩溃了因为 sin(z) 是另一个函数的输入,它只接受 [-1, 1].

范围内的值

此外,我无权访问其他函数,我只能发送一个值,但当 sin(z) returns 大于 1 或小于 - 的数字时它会一直崩溃1.

有什么办法可以弄清楚 sin(z) 这样做的原因吗?

这似乎是一个浮点数错误;参见 this similar post。因此,对于非常大的值,由于舍入误差,sin 函数 return 计算的值略高于 1。

为了解决您的问题,我会将 return 值上限设为 1。具体来说,return min 1 (sin z) 而不是直接 sin z

编辑:将 max 替换为 min

sin :: Double -> Double 函数 returns 对于所有 finite 输入,一个严格介于 -11 之间的数字,无论如何大。特别是,对于最大的可表示有限正双精度数,它 returns 的值大约为 0.005:

> sin (1.7976931348623157E+308 :: Double)
4.961954789184062e-3

并且对于最大的可表示有限负双精度数,它returns一个值是它的负值:

> sin (-1.7976931348623157E+308 :: Double)
-4.961954789184062e-3

毫无疑问,您对 sin 的输入超出了 Double 的有限范围。例如,以下双精度数实际上不能表示为有限双精度数,而是“四舍五入”为无穷大:

> 1.7976931348623159E+308 :: Double
Infinity

如果你将这样一个无穷大的值提供给 sin,你会得到 NaN:

> sin (1.7976931348623159E+308 :: Double)
NaN

这无疑会在输入到期望 -11 之间的有限数字的函数时引起问题。这可以通过 min:

来“修复”
> min (sin (1.7976931348623159E+308 :: Double)) 1
1.0

但是这个修复在很大程度上是无用的,因为你有一个更大的问题正在发生。

对于这么大的数字,Double 的精度大约为正负 1e292。也就是说,这个大小的两个“相邻”可表示有限双精度数大约相隔 1e292,并且两个这样的数字的 sin 也可能是 -11 之间的随机数,完全无关您要完成的任何计算。无论您尝试使用这些数字做什么,都不可能如您所愿。