这是人们自计算机诞生以来就遇到的标准问题。因此,古老的printf(Haskell 或多或少地从 C 复制而来)完美地解决了这个问题。
import Text.Printf
formatPence = printf "%.2f" . (/100) . fromIntegral
哦,要注意...这对于非常大的数量有一个精度问题,因为Double(隐式用于除法)没有Int 那样高分辨率。
Prelude Text.Printf> formatPence 10000000000000013
"100000000000000.13"
Prelude Text.Printf> formatPence 100000000000000013
"1000000000000000.10"
Prelude Text.Printf> formatPence 1000000000000000013
"10000000000000000.00"
因此,如果您要处理数万亿美元的金额,最好不要使用它。
(我想如果你处理的是这样的金额,你可能不会在这里问这个问题......你也不会使用Int。)
要解决此问题,您可以使用原始方法,但仍使用 printf 格式化多余的零:
type Price' = Integer
formatPence' :: Price' -> String
formatPence' a = show (a `div` 100) ++ "." ++ printf "%02u" (a `mod` 100)
这将适用于任意可笑的金额:
> formatPence' 1000000000000000103
"10000000000000001.03"
> formatPence' 6529857623987620347562395876204395876395762398417639852764958726398527634972365928376529384
"65298576239876203475623958762043958763957623984176398527649587263985276349723659283765293.84"
请注意,手动 div/mod 会导致出现负数问题,但这很容易解决。