I have a function in Haskell which looks like this
type Price = Int
formatPence :: Price -> String
formatPence a = show (a `div` 100) ++ "." ++ show(a `mod` 100)
so that, for example, if I input formatPence 1023
, the output would be "10.23"
. But I have a problem if I input 1202
because the output would be "12.2"
. What should I add? Thanks :)
Perhaps you wanted one of the various show*Float
functions in Numeric
?
> :m Numeric
> showFFloat (Just 2) 123.456 ""
123.45
That's a standard problem that people have had ever since the infancy of computers. Hence it's perfectly well solved by the age-old printf
(which Haskell more or less copied from C).
import Text.Printf
formatPence = printf "%.2f" . (/100) . fromIntegral
Oh, to note... this has a precision problem for very large amounts, because Double
(which is implicitly used for the division) doesn't have as high resolution as Int
.
Prelude Text.Printf> formatPence 10000000000000013
"100000000000000.13"
Prelude Text.Printf> formatPence 100000000000000013
"1000000000000000.10"
Prelude Text.Printf> formatPence 1000000000000000013
"10000000000000000.00"
So if you're dealing with amounts of multiple trillion dollars, better not use this.
(I suppose if you were dealing with such amounts, you probably wouldn't ask this question here... and you wouldn't be using Int
.)
To fix this, you can use your original approach, but still use printf
to format the extra zero:
type Price' = Integer
formatPence' :: Price' -> String
formatPence' a = show (a `div` 100) ++ "." ++ printf "%02u" (a `mod` 100)
This will then work with arbitrarily ludicrous amounts:
> formatPence' 1000000000000000103
"10000000000000001.03"
> formatPence' 6529857623987620347562395876204395876395762398417639852764958726398527634972365928376529384
"65298576239876203475623958762043958763957623984176398527649587263985276349723659283765293.84"
Note that the manual div/mod leads in a problem for negative amounts, but that's easy to fix.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With