我在Haskell中有一个看起来像这样的函数
type Price = Int
formatPence :: Price -> String
formatPence a = show (a `div` 100) ++ "." ++ show(a `mod` 100)
因此,例如,如果我输入formatPence 1023
,则输出为"10.23"
。但是如果输入1202
我会遇到问题,因为输出会是"12.2"
。我应该添加什么?谢谢:))
答案 0 :(得分:6)
这是人们从计算机初期就开始的标准问题。因此,它很好地解决了古老的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导致负数问题,但这很容易修复。
答案 1 :(得分:6)
也许你想要show*Float
中的各种Numeric
函数之一?
> :m Numeric
> showFFloat (Just 2) 123.456 ""
123.45
答案 2 :(得分:0)
您需要将小数点后的部分用零填充。
twoDP :: Int -> String
twoDP v = if length str == 1 then '0':str else str
where str = show v
您可以编写更通用的填充函数:
leadingZeros :: Int -> Int -> String
leadingZeros n v = replicate (n - length str) '0' ++ str
where str = show v
不要为这种事情乱用“show”或“printf”的浮点版本:那种方式就是疯狂。