[clean-list] Python's "fix" function in Clean

Siegfried Gonzi siegfried.gonzi@stud.uni-graz.at
Tue, 06 May 2003 11:23:03 +0200


>
>
>

I once complaint about Clean's scarce libraries for handling formatted 
output. The following is a first step:

Maybe you are already familar with Python's fix function:

==
from fpformat import*
fix(2.23231312123123312312,2)
==

fix convertes a number to a specific precision and if needed fills up 
traling zeros and delivers a string for formatted output, e.g:

fix(2.3,3) -> 2.300

I wrote a similar function for Clean (you can literally translate it to 
Haskell), with the caveat that it only works the same as Python's fix 
for floating point values with single precision. The crux actually is 
that Clean's native "toString" function "fails" when converting a huge 
integer number. I think Python uses some bit representation, because 
this works under Python: fix(32231231123123124433422352545.3545544545,123)

My Clean version works right with the small "drawback" that if a number 
is greater than 10^9 it is given back as toString(x) and if the 
precision is specified greater than 9 it will be set back to 9, e.g.

(fix 2.3 120) would result in 2.300000000 and not in 2.300000000000.....
as it would happen under Python's fix. But who wants to store a number 
with 120 "pseudo" precision digits?

You can convert Clean's fix function for formatted output:

==
module fix9
import StdEnv

fix:: Real Int -> String
fix val n
    # n = (if (n>9) 9 n)
    | abs(val)>=10.0^9.0 = toString(val)
    | n<0 = "0"
    | n==0 = toString(toInt(round val))
    # exp_n = 10.0^toReal(n)
    # f = (round (val*exp_n))/exp_n
    # f = abs val
    # t = toInt(truncate f)
    # s = toString(toInt(round (exp_n*(f-toReal(t)))))
    # nzeros = length [x\\x<-:s]
    = (whatSign val)+++(toStringt)
                    +++"."+++{'0'\\x<-[1..(n-nzeros)]}+++s
where
    round:: Real -> Real
    round x = toReal(toInt(x))
    //
    truncate:: Real -> Real
    truncate x
        | x<0.0 = toReal(toInt(x+0.5))
        = toReal(toInt(x-0.5))
    //
    whatSign::Real -> String
    whatSign x
       | x<0.0 = "-"
       = ""

//Start = fix (-0.000011) 2
//Start = fix 2.333333 1
//Start = fix 0.01 3
//Start = fix 0.01 0
//Start = fix -2322332231312312123312123.33 12
Start = fix 1234.34 5
==


fix 0.03 0 --> "0"
fix -2.334444 1 --> "-2.3"
fix 2.3454 5 --> "2.34540"
fix 2.89 1 --> "2.9"
fix (10.0^12.0) 123 --> "1e12" (Clean's native toString and Python would 
put out a very long string; but as I said my function would also work 
right if toString were not limited to 32bit, I think)


Regards,
S. Gonzi