将浮点数四舍五入到特定的小数位数

Round a float to a specific number of decimal places

我正在尝试显示一个浮点数但将其四舍五入,以便

f = 5.545

显示为:5.55

f = 5.544 

显示为:5.54

我见过只显示前两位小数的方法,但我想四舍五入。

谢谢!

这是因为浮点数在计算机中的表示方式:它们实际上是以 2 为基数,而不是以 10 为基数(有点过于简单化,但已经足够好了)。因此,当您输入 0.545 时,计算机实际上将其记录为 0.5499999999... - 非常接近 0.545,但略小。由于它小于 0.545,因此四舍五入为 0.54.

也就不足为奇了

如果您确实需要精确的 10 进制数, 您应该使用 Decimal 而不是 FloatDouble。该包特别注意以 10 为基数表示浮点数而不会丢失。

x :: Decimal
x = 0.545

show x
> "0.545"

需要注意的是 printf 不支持 Decimal,因此您必须通过 roundTo 舍入并通过 show 转换为字符串来显示它。 roundTo 做 "banker's rounding" 的另一个警告 - 如果最后一位数字是五,它四舍五入到最近的 even 数字,所以我们需要抵消它作为特殊情况(我找不到按算术规则舍入的现成函数):

displayDecimal :: Decimal -> String
displayDecimal x = show (rounded + compensate)
    where rounded = roundTo 2 x
          compensate = if (x - rounded) == 0.005 then 0.01 else 0

displayDecimal 0.545
> "0.55"

displayDecimal 0.5450000000001
> "0.55"

displayDecimal 0.544
> "0.54"

displayDecimal 0.5449999999999
> "0.54"

但是,如果您只希望它适用于小数点后三位的数字,您可以在四舍五入前添加一个非常小的值,例如0.00001 ].该值足够小,不会弄乱您的实际数字,但又足够大以补偿 base-2 与 base-10 的差异:

displayRounded :: Double -> String            
displayRounded x = printf "%.2f" (x + 0.00001)

displayRounded 0.544
> "0.54"

displayRounded 0.545
> "0.55"

所以我没有找到真正的解决方案,但我意识到了一些事情:

Printf 已经完成了这项工作,但不是我想要的。 比方说我想舍入 1.445,它会显示 1.44。但是如果这个数字是1.446,那么它就会显示1.45。

不完全是我想要的,但足够接近了。