[ANN] deka - decimal arithmetic

Announcing deka, a library for decimal arithmetic. Why decimal arithmetic is important is discussed at length at http://speleotrove.com/decimal/ but for a short explanation, go into ghci and type: print $ 0.1 + 0.1 + 0.1 This is 0.3, right? But on my machine I get 0.3 plus a small fraction, which is simply not acceptable for applications where it is essential to get exact results, such as financial applications. deka is a binding to the decNumber C library, a thoroughly tested and fast implementation of decimal arithmetic. deka is fully tested and I encourage you to run the tests using the usual "cabal test" method. deka is available at http://hackage.haskell.org/package/deka and is on Github at https://github.com/massysett/deka Because deka is a binding to the decNumber C library, first you will need to install decNumber. An easy to install version with the GNU autotools is at: https://github.com/massysett/decnumber/releases decNumber's website is at http://speleotrove.com/decimal/decnumber.html A literate Haskell file illustrating the use of deka is available at https://github.com/massysett/deka/blob/master/lib/Data/Deka/Docs/Examples.lh...

Note there's some existing support for this in `base`: On Sat, 2014-02-08 at 15:06 -0500, Omari Norman wrote:
but for a short explanation, go into ghci and type:
print $ 0.1 + 0.1 + 0.1
λ print $ (0.1 + 0.1 + 0.1 :: Double) 0.30000000000000004 λ :m + Data.Fixed λ print $ (0.1 :: Fixed E1) + (0.1 :: Fixed E1) + (0.1 :: Fixed E1) 0.3 Nicolas

On Sat, Feb 8, 2014 at 3:39 PM, Nicolas Trangez
Note there's some existing support for this in `base`:
On Sat, 2014-02-08 at 15:06 -0500, Omari Norman wrote:
but for a short explanation, go into ghci and type:
print $ 0.1 + 0.1 + 0.1
λ print $ (0.1 + 0.1 + 0.1 :: Double) 0.30000000000000004
λ :m + Data.Fixed
Key word there is "Fixed"; deka supports floating point with up to 34 digits of precision but, yes, Data.Fixed does solve some of this problem.

* Omari Norman
On Sat, Feb 8, 2014 at 3:39 PM, Nicolas Trangez
wrote: Note there's some existing support for this in `base`:
On Sat, 2014-02-08 at 15:06 -0500, Omari Norman wrote:
but for a short explanation, go into ghci and type:
print $ 0.1 + 0.1 + 0.1
λ print $ (0.1 + 0.1 + 0.1 :: Double) 0.30000000000000004
λ :m + Data.Fixed
Key word there is "Fixed"; deka supports floating point with up to 34 digits of precision but
So it is fixed, too? I'm not sure "Fixed" qualifies as a key word, then :) Note that Data.Fixed doesn't put any restrictions on the (fixed) precision. You could easily define E34. So yeah, a comparison with Data.Fixed would be nice to see. Is deka faster? By how much? Does it support any additional operations? Which ones? Roman

On Sat, Feb 8, 2014 at 4:12 PM, Roman Cheplyaka
So it is fixed, too? I'm not sure "Fixed" qualifies as a key word, then :)
Note that Data.Fixed doesn't put any restrictions on the (fixed) precision. You could easily define E34.
No, it is not fixed.
digits . unDeka . fromJust . strToDeka $ "3.00" 3
digits . unDeka . fromJust . strToDeka $ "3.0000" 5
The precision is determined at runtime. In contrast, with Data.Fixed, the programmer sets the precision at compile time. There is no difference between
3 :: Fixed E6
and
3.00 :: Fixed E6
These issues are discussed at http://speleotrove.com/decimal/decifaq1.html#tzeros but if your reaction is "so what, it's just some extra zeroes and at compile time I can just use E34", then by all means, keep using Fixed :) Also, note that you get 34 significant digits, but that doesn't mean the exponent is limited to 34.
let x = fromJust . strToDeka $ "3E-200" let y = fromJust . strToDeka $ "4E-200" x + y Deka {unDeka = 7E-200}
...which you could do in Fixed, true. If you defined E200 first. But, oops, now I need E250... Really this is a binding to decNumber, which implements the General Decimal Arithmetic Specification, so see if decNumber and that specification scratch an itch. If they don't, use Fixed, or Decimal (also on Hackage) or something else...

* Omari Norman
Also, note that you get 34 significant digits, but that doesn't mean the exponent is limited to 34.
let x = fromJust . strToDeka $ "3E-200" let y = fromJust . strToDeka $ "4E-200" x + y Deka {unDeka = 7E-200}
...which you could do in Fixed, true. If you defined E200 first. But, oops, now I need E250...
I see now. So this is a decimal floating-point numbers library, which also attempts to track the precision of numbers. Does this sound right? Roman

On Sat, Feb 8, 2014 at 5:00 PM, Roman Cheplyaka
* Omari Norman
[2014-02-08 16:45:02-0500] Also, note that you get 34 significant digits, but that doesn't mean the exponent is limited to 34.
let x = fromJust . strToDeka $ "3E-200" let y = fromJust . strToDeka $ "4E-200" x + y Deka {unDeka = 7E-200}
...which you could do in Fixed, true. If you defined E200 first. But, oops, now I need E250...
I see now. So this is a decimal floating-point numbers library, which also attempts to track the precision of numbers. Does this sound right?
That's roughly right, yes. I would say"attempts" is too soft a word. decNumber and, therefore, deka, tracks every significant digit and at least maintains that significance. If it trashes significant digits without notifying you, it's a bug; please report it. The differences between Data.Fixed and this library are so huge (Fixed manipulates Integers alone; decNumber stores numbers as binary-coded decimal coefficients and integer exponents) that I didn't even think to compare them, and I won't be the one to draw performance comparisons between the two because deka is for situations where solutions like Fixed are simply wrong. Fixed does me no good, no matter how fast it is, so there's no reason for me to know how it performs.
participants (3)
-
Nicolas Trangez
-
Omari Norman
-
Roman Cheplyaka