Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Engineering notation with Haskell

Is there a existing Haskell function which provide an engineering notation formatting (as String)?

If not, I read that printf can be extended by adding an instance to PrintfArg. Do you believe this is a good solution ?


By engineering notation, I mean an exponent notation whose exponent is a multiple of 3.

like image 432
JeanJouX Avatar asked Apr 28 '15 16:04

JeanJouX


1 Answers

After some research, I manage to get what I want. The function to get the engineering format work in a few steps :

1. Dissociate the exponent from the mantissa

It's necessary to get the exponent apart of the mantissa. The function decodeFloat (provided by base) decode a floating point number and return both the mantissa and the exponent in power of 2 (mant2 * 2 ^ ex2).

2. Get the mantissa and exponent expressed in the correct base

A conversion in power of 10 is required. This is the role of this function.

decompose :: Double -> (Double,Int)
decompose val = if mant2 > 0 
                     then (mant10,ex10)
                     else (-mant10,ex10)
  where
        (mant2,ex2) = decodeFloat val
        res = logBase 10 (fromIntegral (abs mant2)::Double) + logBase 10 (2 ** (fromIntegral ex2::Double)) 
        ex10 = floor res
        mant10 = 10**(res - (fromIntegral ex10::Double))

3. Set the exponent at a multiple of 3

The function ingen test the result of the integer division of the exponent and perform the adjustement on mantissa and exponent.

ingen :: Double -> (Double,Int)
ingen val 
  | mod ex 3 == 0 = (mant,ex)
  | mod ex 3 == 1 = (mant*10,ex-1)
  | mod ex 3 == 2 = (mant*100,ex-2)
  where
        (mant,ex) = decompose val

Here are some conversions :

Prelude> ingen 10e7
(99.99999999999979,6)
Prelude> ingen 10e-41
(100.0,-42)
Prelude> ingen (-72364e81)
(-72.36399999999853,84)

I performed some tests with quickCheck on a wide range and a large amount of value. The conversion seems to work well despite a very small difference of value (rounding during the calculations due to the precision?).

However, another verifications should be made.

If you find a mistake or an improvement in these functions, please share.

like image 122
JeanJouX Avatar answered Sep 19 '22 14:09

JeanJouX