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 输入,一个严格介于 -1
和 1
之间的数字,无论如何大。特别是,对于最大的可表示有限正双精度数,它 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
这无疑会在输入到期望 -1
和 1
之间的有限数字的函数时引起问题。这可以通过 min
:
来“修复”
> min (sin (1.7976931348623159E+308 :: Double)) 1
1.0
但是这个修复在很大程度上是无用的,因为你有一个更大的问题正在发生。
对于这么大的数字,Double
的精度大约为正负 1e292。也就是说,这个大小的两个“相邻”可表示有限双精度数大约相隔 1e292,并且两个这样的数字的 sin
也可能是 -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 输入,一个严格介于 -1
和 1
之间的数字,无论如何大。特别是,对于最大的可表示有限正双精度数,它 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
这无疑会在输入到期望 -1
和 1
之间的有限数字的函数时引起问题。这可以通过 min
:
> min (sin (1.7976931348623159E+308 :: Double)) 1
1.0
但是这个修复在很大程度上是无用的,因为你有一个更大的问题正在发生。
对于这么大的数字,Double
的精度大约为正负 1e292。也就是说,这个大小的两个“相邻”可表示有限双精度数大约相隔 1e292,并且两个这样的数字的 sin
也可能是 -1
和 1
之间的随机数,完全无关您要完成的任何计算。无论您尝试使用这些数字做什么,都不可能如您所愿。