【发布时间】:2019-09-20 21:13:54
【问题描述】:
使用 ghci 8.6.5
我想计算一个整数输入的平方根,然后将其四舍五入并返回一个整数。
square :: Integer -> Integer
square m = floor $ sqrt $ fromInteger m
它有效。 问题是,对于这个特定的大数字作为输入:
4141414141414141*4141414141414141
我得到了错误的结果。
抛开我的功能,我在 ghci 中测试这个案例:
> sqrt $ fromInteger $ 4141414141414141*4141414141414141
4.1414141414141405e15
错了……对吗?
但很简单
> sqrt $ 4141414141414141*4141414141414141
4.141414141414141e15
这更像是我对计算的期望......
在我的函数中,我必须进行一些类型转换,我认为 fromIntegral 是要走的路。因此,使用它,我的函数为 4141...41 输入给出了错误的结果。
在运行 sqrt 之前,我无法弄清楚 ghci 在类型转换方面的隐含作用。因为 ghci 的转换允许正确计算。
为什么我说这是异常情况:其他号码不会出现问题,例如 5151515151515151 或 3131313131313131 或 4242424242424242 ...
这是一个 Haskell 错误吗?
【问题讨论】:
-
看起来像浮点溢出。
-
我不认为这是重复的。这似乎是一个明显的错误:
fromInteger $ 4141414141414141*4141414141414141产生1.7151311090705025e31,但1.7151311090705027e31是有效的Double,并且更接近正确的整数17151311090705026668707274767881。所以fromInteger应该归咎于此,而不是四舍五入! -
对于精确的 bignum 平方根(即保持在
Integer内并且永远不会通过Double),您可能会喜欢 arithmoi。 -
您可以使用
(read . show)而不是fromInteger来规避舍入问题。这就是dhall实现其Integer/toDouble操作的方式。
标签: haskell floating-point type-conversion precision largenumber