将浮点数四舍五入到特定的小数位数
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
而不是 Float
或 Double
。该包特别注意以 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。
不完全是我想要的,但足够接近了。
我正在尝试显示一个浮点数但将其四舍五入,以便
f = 5.545
显示为:5.55
而
f = 5.544
显示为:5.54
我见过只显示前两位小数的方法,但我想四舍五入。
谢谢!
这是因为浮点数在计算机中的表示方式:它们实际上是以 2 为基数,而不是以 10 为基数(有点过于简单化,但已经足够好了)。因此,当您输入 0.545
时,计算机实际上将其记录为 0.5499999999...
- 非常接近 0.545
,但略小。由于它小于 0.545
,因此四舍五入为 0.54
.
如果您确实需要精确的 10 进制数, 您应该使用 Decimal
而不是 Float
或 Double
。该包特别注意以 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。
不完全是我想要的,但足够接近了。