Haskell中如何精确缩放浮点数?用round/ceiling会有精度问题吗?
缩放四位小数数字为整数时round/ceiling的精度问题分析
会出现精度问题,但具体表现取决于你使用的取整函数,核心原因是二进制浮点数无法精确表示所有十进制小数——比如1.009这类数值,存储时本身就带有微小误差,乘以缩放因子后误差会被放大,导致结果偏离预期的整数。
看你给出的GHCI示例:
第一个示例(缩放1000倍)
ghci> let x = 1.009 * 1000 ghci> x 1008.9999999999999 ghci> round x 1009 ghci> floor x 1008 ghci> ceiling x 1009
这里1.009存储为浮点数后,乘以1000的实际结果是略小于1009的1008.9999999999999:
round做四舍五入,刚好能得到预期的1009;ceiling取大于等于该数的最小整数,也能得到1009;- 但
floor取小于等于该数的最大整数,就得到了1008,和预期不符。
第二个示例(缩放100000000倍)
ghci> let y = 1.009 * 100000000 ghci> y 1.0089999999999999e8 ghci> round y 100900000 ghci> floor y 100899999 ghci> ceiling y 100900000
同理,缩放后的实际值略小于100900000,round和ceiling能给出预期结果,但floor依然出错。
如果要彻底避免这类问题,建议用十进制小数类型(比如Haskell中的Decimal或Fixed类型)来处理,这类类型能精确表示四位小数的数值,缩放后直接取整就不会有误差。
内容的提问来源于stack exchange,提问作者pseuyi
相关产品推荐
相关产品推荐

