kostmo
kostmo

Reputation: 6340

format float with stripped trailing zeros and decimal point, switching to scientific notation for large numbers in haskell

I am looking for a method in Haskell to format a floating point number in exactly the way described in this (Java) question, for optimal compactness. I think this may also be referred to as "normalization".

I will copy the example scenarios from that question here:

2.80000 -> Should be formatted as "2.8"

765.000000 -> "765" (notice how the decimal point is also dropped)

0.0073943162953 -> "0.00739432" (limit digits of precision—to 6 in this case)

0.0000073943162953 -> "7.39432E-6" (switch to scientific notation if the magnitude is small enough—less than 1E-5 in this case)

7394316295300000 -> "7.39432E+6" (switch to scientific notation if the magnitude is large enough—for example, when greater than 1E+10)

0.0000073900000000 -> "7.39E-6" (strip trailing zeros from significand in scientific notation)

0.000007299998344 -> "7.3E-6" (rounding from the 6-digit precision limit causes this number to have trailing zeros which are stripped)

Is there a built-in library in Haskell that will do this, or do I have to roll my own?

Upvotes: 2

Views: 605

Answers (1)

lehins
lehins

Reputation: 9767

What you are looking for is formatRealFloat from GHC.Float module. I am not sure if there is documentation available for that module on haskell.org, but here is a summary of the module: http://www.cis.upenn.edu/~bcpierce/courses/advprog/resources/base/GHC.Float.html

You will need to modify it of course to suit your needs, but here is an example:

import GHC.Float

formatFloat :: RealFloat a => a -> String
formatFloat v
  | v == 0                          = "0"
  | abs v < 1e-5 || abs v > 1e10    = formatRealFloat FFExponent Nothing v
  | v - fromIntegral (floor v) == 0 = formatRealFloat FFFixed   (Just 0) v
  | otherwise                       = formatRealFloat FFGeneric  Nothing v

Naturally, it will only work with ghc compiler.

Upvotes: 5

Related Questions