在Haskell中打印浮点数

时间:2016-03-28 18:40:39

标签: haskell show floating

我在Haskell中有一个看起来像这样的函数

type Price    = Int

formatPence :: Price -> String
formatPence a = show (a `div` 100) ++ "." ++ show(a `mod` 100)

因此,例如,如果我输入formatPence 1023,则输出为"10.23"。但是如果输入1202我会遇到问题,因为输出会是"12.2"。我应该添加什么?谢谢:))

3 个答案:

答案 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”的浮点版本:那种方式就是疯狂。