Ugly doubles - why 2.9000000000000004 instead of 2.9?

when I do 5.2 - 2.3 in ghci, I will get 2.9000000000000004 instead of 2.9. Also such ugly (and for human WRONG) results appear elsewhere when working with Double or Float.

Why is this happening? (this is just for curiosity, not for my real question)

My real question is: How can I tell ghci not to do this, and show the results of operations in doubles just like any other programming language (and calculator), and just like every 15-year-old will write them?

It is so annoying when I use ghci as a good calculator and work on lists on which I perform such operations.

map ((-)2.3) [4.0, 3.8, 5.2, 6.4, 1.3, 8.3, 13.7, 9.0, 7.5, 2.4] [-1.7000000000000002,-1.5,-2.9000000000000004,-4.1000000000000005,0.9999999999999998,-6.000000000000001,-11.399999999999999,-6.7,-5.2,-0.10000000000000009] 

It just doesn't help when using numbers on a piece of paper

Thanks in advance:)

+7
haskell
source share
4 answers

How can I tell ghci not to do this, and show the results of operations in doubles just like any other programming language (and calculator), and just like every 15-year-old will write them?

Since these results are actual GHCI results (and your standard calculator * ) calculates, you cannot change the internal representation of the result ( see TNI answer ). Since you only want to show a fixed number of decimal places, it is more a matter of presentation (compare with printf("%f.2",...) in C).

A solution to this can be found in https://stackoverflow.com/a/312960/197030/... It can be applied as follows:

 import Numeric fixedN :: (RealFloat b) => Int -> b -> String fixedN ab = showFFloat (Just a) b "" map (fixedN 2 . (-)2.3) [4.0, 3.8, 5.2, 6.4, 1.3, 8.3, 13.7, 9.0, 7.5, 2.4] -- result: ["-1.70","-1.50","-2.90","-4.10","1.00","-6.00",...] 

Please note that this will not be possible if you want to continue the calculation. If you need accurate arithmetic, you can still use Rationals . Do not forget that your entry should be rational in this case too.

* Yes, even your standard calculator does the same, the only reason you don’t see it is a fixed view, it cannot display more than a fixed number of decimal places.

+8
source share

Why is this happening?

Since some floating point numbers cannot be represented by a finite number of bits without rounding. Floating-point numbers have a limited number of digits; they cannot represent all valid digits : when the number is larger than the format allows, the remaining objects are omitted - the number is rounded.

You should probably read What Every Computer Scientist Should Know About Floating-Point Arithmetic and this answer .

+18
source share

It is the nature of floating point numbers that they cannot accurately represent real (or rational) numbers. Haskell's default conversion to string ensures that when you read the number again, you get exactly the same representation. If you need a different way to print numbers, you can make your own type, which displays numbers in different ways.

Something like (untested):

 newtype MyDouble = MyDouble {getMyDouble :: Double} deriving (Eq, Ord, Num, Real, RealFrac, Fractional, Floating) instance Show MyDouble where show = printf "%g" . getMyDouble default (MyDouble) 

This creates a copy of type Double , but with a different instance of Show , which simply prints a few decimal places. The default declaration allows the compiler to select this type when there is uncertainty. Oh, and to do this job, you will need several language extensions.

You can also try the CReal type from the numbers package.

+3
source share

How to tell ghci not to do this and show the results of operations in doubles, as any other programming language (and calculator) will

Have you really tried "any other programming language"? Or are you just kidding me?

FWIW, here is the interpreter output for a language using the JVM:

 frege> 5.2 - 2.3 2.9000000000000004 

It looks like you will get the same result with all JVM languages. And since the JVM is written in C ++, it is likely that the result will be the same. And since most of the time languages ​​are written in C / C ++, perhaps you get the same result with these languages. If they are not so "user friendly" and perform rounding, you did not ask.

+3
source share

All Articles