0

I want to calculate 0.2 * 0.2 but the result would not be 0.04.

>0.2 * 0.2
4.000000000000001e-2

I know this happened in any programing languages. I wonder what wulod be the most common way to calculate floating point numbers in Haskell?

Like BigDecimal in Java,

BigDecimal result = new BigDecimal("0.2").multiply(new BigDecimal("0.2"));
double value = result.doubleValue();

does Haskell have any functions or tricks like this?

rere
  • 51
  • 5
  • Yes, the binary64 product of the binary64 number represented as `0.2` by itself is the binary64 number represented as `4.000000000000001e-2`. This **is** calculating floating-point numbers. What do you expect the result of 1 / 3 * 3 will be if Haskell does have something like BigDecimal? – Pascal Cuoq Oct 16 '15 at 02:26
  • the easiest thing you can do is round numbers while printing converting `0.00123999999???` to `0.00124` and comparing with difference. If you need exact form of number then use arbitrary precision string based big decimal numbers library (or write one yourself) – Spektre Oct 19 '15 at 10:53

2 Answers2

4

This is how floating point arithmetic works (in any language, not just Haskell) so you don't want floating point. See, for example, this question.

You can use Rational from Data.Ratio for working with exact rational numbers:

ghci> import Data.Ratio
ghci> 0.2 :: Rational
1 % 5
ghci> 0.2 * 0.2 :: Rational
1 % 25

If you want to convert it back to floating point (which could potentially result in floating point errors as well, due to the nature of floating point), you can use fromRat from Numeric:

ghci> import Numeric
ghci> fromRat ((0.2 * 0.2) :: Rational)
4.0e-2

A side note about Haskell's numeric literals

This isn't casting (Haskell doesn't have casting, at least not in this sense). Numeric literals are overloaded, so they can take on any type that is an instance of the Num type class. It isn't necessary to understand this fully right now, but it is good to know and look into at some point.

Community
  • 1
  • 1
David Young
  • 10,713
  • 2
  • 33
  • 47
  • Is there a nice function somewhere for converting rationals to their closest n-digit or n-digit-after-decimal or whatever representation? Or would that have to be done by hand? – dfeuer Oct 16 '15 at 03:00
  • Is there any functions to convert RealFloat to String with n-dgit format? – rere Oct 19 '15 at 16:57
2

In addition to the Rational type, you might have a look at the numbers package.

In particular, two types might be of interest:

  • a BigFloat type - allows you to select the precision
  • a Fixed type - allows you to select the number of decimals
  • a CReal type for exact representations of constructible real numbers

Other packages to investigate:

ErikR
  • 51,541
  • 9
  • 73
  • 124