【发布时间】:2014-11-10 12:43:07
【问题描述】:
我正在尝试使用长度等于truncate (log10(x)+1) 的事实来计算 Haskell 中整数的长度。
使用我创建的整数:
len :: Integer -> Integer
len i = toInteger (truncate (logBase 10 (fromIntegral i)) + 1)
很遗憾,并非所有数字的长度都正确。我尝试了几种不同的情况,发现:
logBase 10 10 = 1.0
logBase 10 100 = 2.0
logBase 10 1000 = 2.9999..6
logBase 10 10000 = 4.0
logBase 10 100000 = 5.0
logBase 10 1000000 = 5.9999999
logBase 10 1000 不返回 3.0 是否有原因?如何获得以 10 为底的 1000 的正确对数值?
【问题讨论】:
-
logBase定义为log y / log x;除法可能是罪魁祸首,虽然log是正确的(关于四舍五入),但它们的除法不一定是。 -
@BartekBanachewicz 那么有没有办法得到正确的结果?尝试使用 (log 1000) / (log 10),但仍然是 2.99996。猜测 log-values 可能会向下舍入 1000 并向上舍入 10,因此它会略小于 3。
-
假设
log不是必需的,你可以避免反复除以10(以及10的更高幂)的浮点运算。 -
@Pphoenix 获得正确结果的最简单方法是使用
numbers包,然后调用logBase 10 1000 :: BigFloat Prec50,然后将其四舍五入为浮点数或双精度数。最简单,但不一定是最好的。 -
如果您不需要
Double浮点精度,那么请改用Float类型,它似乎没问题。比如logBase 10 (1000 :: Float)会返回3.0或者功能上logBase 10 . (fromInteger :: Integer -> Float) $ 1000会做同样的事情。
标签: haskell logarithm rounding-error