- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers

# 0.4 * 0.4 is not 0.16, why? (is this a bug?)

Tue, 2010-03-30, 04:52

scala> 0.4*0.4

res0: Double = 0.16000000000000003 //NOT 0.16

scala> 0.7*0.4

res1: Double = 0.27999999999999997 //NOT 0.28

I used scala-2.8.0.Beta1-prerelease.

res0: Double = 0.16000000000000003 //NOT 0.16

scala> 0.7*0.4

res1: Double = 0.27999999999999997 //NOT 0.28

I used scala-2.8.0.Beta1-prerelease.

Tue, 2010-03-30, 05:37

#2
Re: 0.4 * 0.4 is not 0.16, why? (is this a bug?)

Maybe you could use a Java BigDecimal

On Mon, Mar 29, 2010 at 11:52 PM, Himanshu wrote:

> scala> 0.4*0.4

> res0: Double = 0.16000000000000003 //NOT 0.16

>

> scala> 0.7*0.4

> res1: Double = 0.27999999999999997 //NOT 0.28

>

> I used scala-2.8.0.Beta1-prerelease.

>

Tue, 2010-03-30, 07:37

#3
Re: 0.4 * 0.4 is not 0.16, why? (is this a bug?)

Thanks Daniel and David.. I just tried it on java also, results are exactly the same :)

Tue, 2010-03-30, 15:57

#4
Re: 0.4 * 0.4 is not 0.16, why? (is this a bug?)

Here it is in GHC Haskell

Prelude> 0.4 * 0.40.16000000000000003

And Python>>> 0.4 * 0.40.16000000000000003

And gcc C++

#include <iostream>#include <iomanip>

using namespace std;

int main(int argc, char** argv) { cout << setprecision(55) << 0.4 * 0.4 << endl;}0.16000000000000003108624468950438313186168670654296875

You're going to have to file a lot of bugs.

On Mon, Mar 29, 2010 at 11:32 PM, Himanshu <g [dot] himanshu [at] gmail [dot] com> wrote:

Prelude> 0.4 * 0.40.16000000000000003

And Python>>> 0.4 * 0.40.16000000000000003

And gcc C++

#include <iostream>#include <iomanip>

using namespace std;

int main(int argc, char** argv) { cout << setprecision(55) << 0.4 * 0.4 << endl;}0.16000000000000003108624468950438313186168670654296875

You're going to have to file a lot of bugs.

On Mon, Mar 29, 2010 at 11:32 PM, Himanshu <g [dot] himanshu [at] gmail [dot] com> wrote:

Thanks Daniel and David.. I just tried it on java also, results are exactly the same :)

Tue, 2010-03-30, 18:17

#5
Re: 0.4 * 0.4 is not 0.16, why? (is this a bug?)

You are in a world of surprises. Here is another one with floating

point numbers:

val n = 1.0/0.0 - 1.0/0.0

if (n > 0.0) println("ok")

else if (n < 0.0) println("ok")

else if (n == 0.0) println("ok")

else println("oops")

Also there are things like round off errors which can kill the

accuracy of your result very quickly. Because of this many math

formulas cannot be used directly and need special algorithms.

On Mon, Mar 29, 2010 at 11:52 PM, Himanshu wrote:

> scala> 0.4*0.4

> res0: Double = 0.16000000000000003 //NOT 0.16

>

> scala> 0.7*0.4

> res1: Double = 0.27999999999999997 //NOT 0.28

>

> I used scala-2.8.0.Beta1-prerelease.

>

Tue, 2010-03-30, 19:57

#6
Re: 0.4 * 0.4 is not 0.16, why? (is this a bug?)

On Tue, Mar 30, 2010 at 2:32 AM, Himanshu wrote:

> Thanks Daniel and David.. I just tried it on java also, results are exactly

> the same :)

>

System.out.println(BigDecimal.valueOf(.4).multiply(BigDecimal.valueOf(.4)));

System.out.println(BigDecimal.valueOf(.4).multiply(BigDecimal.valueOf(.7)));

Tue, 2010-03-30, 20:37

#7
Re: 0.4 * 0.4 is not 0.16, why? (is this a bug?)

I know ABC uses bigdecimal by default (and who here ever heard of it? :). I think Ruby and TCL might do it too, not sure.

On Tue, Mar 30, 2010 at 11:48 AM, James Iry <jamesiry [at] gmail [dot] com> wrote:

--

Daniel C. Sobral

I travel to the future all the time.

On Tue, Mar 30, 2010 at 11:48 AM, James Iry <jamesiry [at] gmail [dot] com> wrote:

Here it is in GHC Haskell

Prelude> 0.4 * 0.40.16000000000000003

And Python>>> 0.4 * 0.40.16000000000000003

And gcc C++

#include <iostream>#include <iomanip>

using namespace std;

int main(int argc, char** argv) { cout << setprecision(55) << 0.4 * 0.4 << endl;}0.16000000000000003108624468950438313186168670654296875

You're going to have to file a lot of bugs.

On Mon, Mar 29, 2010 at 11:32 PM, Himanshu <g [dot] himanshu [at] gmail [dot] com> wrote:Thanks Daniel and David.. I just tried it on java also, results are exactly the same :)

--

Daniel C. Sobral

I travel to the future all the time.

Wed, 2010-03-31, 22:37

#8
Re: 0.4 * 0.4 is not 0.16, why? (is this a bug?)

On Tue, Mar 30, 2010 at 16:14, Daniel Sobral wrote:

> I know ABC uses bigdecimal by default (and who here ever heard of it? :). I

> think Ruby

yep

$ irb

>> 0.4*0.4

=> 0.16

>>

> and TCL might do it too, not sure.

>

> On Tue, Mar 30, 2010 at 11:48 AM, James Iry wrote:

>>

>> Here it is in GHC Haskell

>> Prelude> 0.4 * 0.4

>> 0.16000000000000003

>> And Python

>> >>> 0.4 * 0.4

>> 0.16000000000000003

>> And gcc C++

>> #include

>> #include

>> using namespace std;

>> int main(int argc, char** argv) {

>> cout << setprecision(55) << 0.4 * 0.4 << endl;

>> }

>> 0.16000000000000003108624468950438313186168670654296875

>> You're going to have to file a lot of bugs.

>> On Mon, Mar 29, 2010 at 11:32 PM, Himanshu wrote:

>>>

>>> Thanks Daniel and David.. I just tried it on java also, results are

>>> exactly the same :)

>>

>

>

>

> --

> Daniel C. Sobral

>

> I travel to the future all the time.

>

Wed, 2010-03-31, 23:17

#9
Re: 0.4 * 0.4 is not 0.16, why? (is this a bug?)

Nope. Your string is just being truncated

irb(main):014:0> "%.55f" % (0.4 * 0.4)=> "0.1600000000000000310862446895043831318616867065429687500"

On Wed, Mar 31, 2010 at 2:35 PM, Federico Silva <fede [dot] silva [at] gmail [dot] com> wrote:

irb(main):014:0> "%.55f" % (0.4 * 0.4)=> "0.1600000000000000310862446895043831318616867065429687500"

On Wed, Mar 31, 2010 at 2:35 PM, Federico Silva <fede [dot] silva [at] gmail [dot] com> wrote:

On Tue, Mar 30, 2010 at 16:14, Daniel Sobral <dcsobral [at] gmail [dot] com> wrote:

> I know ABC uses bigdecimal by default (and who here ever heard of it? :). I

> think Ruby

yep

$ irb

>> 0.4*0.4

=> 0.16

>>

> and TCL might do it too, not sure.

>

> On Tue, Mar 30, 2010 at 11:48 AM, James Iry <jamesiry [at] gmail [dot] com> wrote:

>>

>> Here it is in GHC Haskell

>> Prelude> 0.4 * 0.4

>> 0.16000000000000003

>> And Python

>> >>> 0.4 * 0.4

>> 0.16000000000000003

>> And gcc C++

>> #include <iostream>

>> #include <iomanip>

>> using namespace std;

>> int main(int argc, char** argv) {

>> cout << setprecision(55) << 0.4 * 0.4 << endl;

>> }

>> 0.16000000000000003108624468950438313186168670654296875

>> You're going to have to file a lot of bugs.

>> On Mon, Mar 29, 2010 at 11:32 PM, Himanshu <g [dot] himanshu [at] gmail [dot] com> wrote:

>>>

>>> Thanks Daniel and David.. I just tried it on java also, results are

>>> exactly the same :)

>>

>

>

>

> --

> Daniel C. Sobral

>

> I travel to the future all the time.

>

--

@fedesilva

Wed, 2010-03-31, 23:37

#10
Re: 0.4 * 0.4 is not 0.16, why? (is this a bug?)

I think groovy uses bigdecimal by default.

Sent from my iPhone

On Mar 31, 2010, at 6:13 PM, James Iry <jamesiry [at] gmail [dot] com> wrote:

Sent from my iPhone

On Mar 31, 2010, at 6:13 PM, James Iry <jamesiry [at] gmail [dot] com> wrote:

Nope. Your string is just being truncated

irb(main):014:0> "%.55f" % (0.4 * 0.4)=> "0.1600000000000000310862446895043831318616867065429687500"

On Wed, Mar 31, 2010 at 2:35 PM, Federico Silva <fede [dot] silva [at] gmail [dot] com (fede [dot] silva [at] gmail [dot] com" rel="nofollow">fede [dot] silva [at] gmail [dot] com)> wrote:On Tue, Mar 30, 2010 at 16:14, Daniel Sobral <dcsobral [at] gmail [dot] com (dcsobral [at] gmail [dot] com" rel="nofollow">dcsobral [at] gmail [dot] com)> wrote:

> I know ABC uses bigdecimal by default (and who here ever heard of it? :). I

> think Ruby

yep

$ irb

>> 0.4*0.4

=> 0.16

>>

> and TCL might do it too, not sure.

>

> On Tue, Mar 30, 2010 at 11:48 AM, James Iry <jamesiry [at] gmail [dot] com (jamesiry [at] gmail [dot] com" rel="nofollow">jamesiry [at] gmail [dot] com)> wrote:

>>

>> Here it is in GHC Haskell

>> Prelude> 0.4 * 0.4

>> 0.16000000000000003

>> And Python

>> >>> 0.4 * 0.4

>> 0.16000000000000003

>> And gcc C++

>> #include <iostream>

>> #include <iomanip>

>> using namespace std;

>> int main(int argc, char** argv) {

>> cout << setprecision(55) << 0.4 * 0.4 << endl;

>> }

>> 0.16000000000000003108624468950438313186168670654296875

>> You're going to have to file a lot of bugs.

>> On Mon, Mar 29, 2010 at 11:32 PM, Himanshu <g [dot] himanshu [at] gmail [dot] com (g [dot] himanshu [at] gmail [dot] com" rel="nofollow">g [dot] himanshu [at] gmail [dot] com)> wrote:

>>>

>>> Thanks Daniel and David.. I just tried it on java also, results are

>>> exactly the same :)

>>

>

>

>

> --

> Daniel C. Sobral

>

> I travel to the future all the time.

>

--

@fedesilva

Wed, 2010-03-31, 23:47

#11
Re: 0.4 * 0.4 is not 0.16, why? (is this a bug?)

Ding ding ding! A winner!

groovy:000> 0.4 * 0.4===> 0.16groovy:000> 0.4 * 0.4 == 0.16===> truegroovy:000> (0.4 * 0.4).getClass() ===> class java.math.BigDecimal

On Wed, Mar 31, 2010 at 3:31 PM, Josh Suereth <joshua [dot] suereth [at] gmail [dot] com> wrote:

groovy:000> 0.4 * 0.4===> 0.16groovy:000> 0.4 * 0.4 == 0.16===> truegroovy:000> (0.4 * 0.4).getClass() ===> class java.math.BigDecimal

On Wed, Mar 31, 2010 at 3:31 PM, Josh Suereth <joshua [dot] suereth [at] gmail [dot] com> wrote:

I think groovy uses bigdecimal by default.

Sent from my iPhone

On Mar 31, 2010, at 6:13 PM, James Iry <jamesiry [at] gmail [dot] com> wrote:Nope. Your string is just being truncated

irb(main):014:0> "%.55f" % (0.4 * 0.4)=> "0.1600000000000000310862446895043831318616867065429687500"

On Wed, Mar 31, 2010 at 2:35 PM, Federico Silva <fede [dot] silva [at] gmail [dot] comfede [dot] silva [at] gmail [dot] com> wrote:

On Tue, Mar 30, 2010 at 16:14, Daniel Sobral <dcsobral [at] gmail [dot] comdcsobral [at] gmail [dot] com> wrote:

> I know ABC uses bigdecimal by default (and who here ever heard of it? :). I

> think Ruby

yep

$ irb

>> 0.4*0.4

=> 0.16

>>

> and TCL might do it too, not sure.

>

> On Tue, Mar 30, 2010 at 11:48 AM, James Iry <jamesiry [at] gmail [dot] comjamesiry [at] gmail [dot] com> wrote:

>>

>> Here it is in GHC Haskell

>> Prelude> 0.4 * 0.4

>> 0.16000000000000003

>> And Python

>> >>> 0.4 * 0.4

>> 0.16000000000000003

>> And gcc C++

>> #include <iostream>

>> #include <iomanip>

>> using namespace std;

>> int main(int argc, char** argv) {

>> cout << setprecision(55) << 0.4 * 0.4 << endl;

>> }

>> 0.16000000000000003108624468950438313186168670654296875

>> You're going to have to file a lot of bugs.

>> On Mon, Mar 29, 2010 at 11:32 PM, Himanshu <g [dot] himanshu [at] gmail [dot] comg [dot] himanshu [at] gmail [dot] com> wrote:

>>>

>>> Thanks Daniel and David.. I just tried it on java also, results are

>>> exactly the same :)

>>

>

>

>

> --

> Daniel C. Sobral

>

> I travel to the future all the time.

>

--

@fedesilva

Mon, 2010-04-05, 17:37

#12
Re: 0.4 * 0.4 is not 0.16, why? (is this a bug?)

Sure, it's a winner, although a fair bit slower than native floating-point which is calculated by hardware routines as oppose to software.

Almost all hardware that we use today implements IEEE 754 (http://en.wikipedia.org/wiki/IEEE_754-1985), which is a binary floating-point mechanism, which handles binary fractions well (2 to the power of minus n). These fractions are 1/2, 1/4, 1/8, 1/16, etc. Unfortunately, we naturally use fractions that are decimals (10 to the power of minus n). These fractions are 1/10, 1/100, 1/1000, 1/10000, etc. We are quite aware that many real number can't be represented in our decimal system exactly (1/3 for example), but it comes as a surprise to us that using a binary system cannot represent 0.1 exactly. The decimal value 0.1 is represented in binary as 0.0001100110011, where the 0011 bits repeat forever. This evaluates as follows:

0.1 ~= 1/16 + 1/32 + 1/256 + 1/512 + 1/4096 + 1/8192 == 0.099609375

(The machine will further translate this to the IEEE 754 standard, so it will be represented differently in memory)

There is a recent update to the IEEE 754 standard (http://en.wikipedia.org/wiki/IEEE_754-2008), which provides for decimal number representations and decimal arithmetic. There are software package in C/C++ that provide this standard, but it will likely be some time (if ever) before we see native hardware implementation from Intel.

I'm not sure how BigDecimal works. By the name, I would assume it implements decimal floating-point arithmetic in software.

--DS

On 31 March 2010 18:45, James Iry <jamesiry [at] gmail [dot] com> wrote:

Almost all hardware that we use today implements IEEE 754 (http://en.wikipedia.org/wiki/IEEE_754-1985), which is a binary floating-point mechanism, which handles binary fractions well (2 to the power of minus n). These fractions are 1/2, 1/4, 1/8, 1/16, etc. Unfortunately, we naturally use fractions that are decimals (10 to the power of minus n). These fractions are 1/10, 1/100, 1/1000, 1/10000, etc. We are quite aware that many real number can't be represented in our decimal system exactly (1/3 for example), but it comes as a surprise to us that using a binary system cannot represent 0.1 exactly. The decimal value 0.1 is represented in binary as 0.0001100110011, where the 0011 bits repeat forever. This evaluates as follows:

0.1 ~= 1/16 + 1/32 + 1/256 + 1/512 + 1/4096 + 1/8192 == 0.099609375

(The machine will further translate this to the IEEE 754 standard, so it will be represented differently in memory)

There is a recent update to the IEEE 754 standard (http://en.wikipedia.org/wiki/IEEE_754-2008), which provides for decimal number representations and decimal arithmetic. There are software package in C/C++ that provide this standard, but it will likely be some time (if ever) before we see native hardware implementation from Intel.

I'm not sure how BigDecimal works. By the name, I would assume it implements decimal floating-point arithmetic in software.

--DS

On 31 March 2010 18:45, James Iry <jamesiry [at] gmail [dot] com> wrote:

Ding ding ding! A winner!

groovy:000> 0.4 * 0.4===> 0.16groovy:000> 0.4 * 0.4 == 0.16===> truegroovy:000> (0.4 * 0.4).getClass() ===> class java.math.BigDecimal

On Wed, Mar 31, 2010 at 3:31 PM, Josh Suereth <joshua [dot] suereth [at] gmail [dot] com> wrote:

I think groovy uses bigdecimal by default.

Sent from my iPhone

On Mar 31, 2010, at 6:13 PM, James Iry <jamesiry [at] gmail [dot] com> wrote:Nope. Your string is just being truncated

irb(main):014:0> "%.55f" % (0.4 * 0.4)=> "0.1600000000000000310862446895043831318616867065429687500"

On Wed, Mar 31, 2010 at 2:35 PM, Federico Silva <fede [dot] silva [at] gmail [dot] comfede [dot] silva [at] gmail [dot] com> wrote:

On Tue, Mar 30, 2010 at 16:14, Daniel Sobral <dcsobral [at] gmail [dot] comdcsobral [at] gmail [dot] com> wrote:

> I know ABC uses bigdecimal by default (and who here ever heard of it? :). I

> think Ruby

yep

$ irb

>> 0.4*0.4

=> 0.16

>>

> and TCL might do it too, not sure.

>

> On Tue, Mar 30, 2010 at 11:48 AM, James Iry <jamesiry [at] gmail [dot] comjamesiry [at] gmail [dot] com> wrote:

>>

>> Here it is in GHC Haskell

>> Prelude> 0.4 * 0.4

>> 0.16000000000000003

>> And Python

>> >>> 0.4 * 0.4

>> 0.16000000000000003

>> And gcc C++

>> #include <iostream>

>> #include <iomanip>

>> using namespace std;

>> int main(int argc, char** argv) {

>> cout << setprecision(55) << 0.4 * 0.4 << endl;

>> }

>> 0.16000000000000003108624468950438313186168670654296875

>> You're going to have to file a lot of bugs.

>> On Mon, Mar 29, 2010 at 11:32 PM, Himanshu <g [dot] himanshu [at] gmail [dot] comg [dot] himanshu [at] gmail [dot] com> wrote:

>>>

>>> Thanks Daniel and David.. I just tried it on java also, results are

>>> exactly the same :)

>>

>

>

>

> --

> Daniel C. Sobral

>

> I travel to the future all the time.

>

--

@fedesilva

Mon, 2010-04-05, 18:37

#13
Re: 0.4 * 0.4 is not 0.16, why? (is this a bug?)

It's not decimal floating point. Unlike a floating point number which has a fixed number of bits, BigDecimal is a bignum meaning the size of possible numbers is limited only by memory (or other similar JVM limitations like object handles). And frankly, if we're going to pay that price, I'd rather have a BigRational (a pair of BigInts) than BigDecimal which can't even represent 1/3 exactly.

On Mon, Apr 5, 2010 at 9:31 AM, Dave Smith <dave.smith.to@gmail.com> wrote:

On Mon, Apr 5, 2010 at 9:31 AM, Dave Smith <dave.smith.to@gmail.com> wrote:

I'm not sure how BigDecimal works. By the name, I would assume it implements decimal floating-point arithmetic in software.

Mon, 2010-04-05, 18:57

#14
Re: 0.4 * 0.4 is not 0.16, why? (is this a bug?)

Well, of course for any rational "base" representation there are

numbers that can't be represented. That is, if you're going to

represent numbers as

... + a1*b^x + a2*b^(x+1) + a3*b^(x+2) + ...

(where the a's and x are integers)

then any number with a prime root that is not shared with the prime

roots of b is not representable.

Clojure uses a Ratio class for arbitrary-precision math -- which I

think is probably the same concept as James' "BigRational" -- just two

BigIntegers: numerator and denominator. Weird performance

characteristics though, since addition can be way more expensive than

multiplication with Ratios.

Best regards,

Brian Maso

(949) 395-8551

brian [at] blumenfeld-maso [dot] com

twitter: @bmaso

skype: brian.maso

LinkedIn: http://www.linkedin.com/in/brianmaso

On Mon, Apr 5, 2010 at 10:26 AM, James Iry wrote:

> It's not decimal floating point. Unlike a floating point number which has a

> fixed number of bits, BigDecimal is a bignum meaning the size of possible

> numbers is limited only by memory (or other similar JVM limitations like

> object handles). And frankly, if we're going to pay that price, I'd rather

> have a BigRational (a pair of BigInts) than BigDecimal which can't even

> represent 1/3 exactly.

>

> On Mon, Apr 5, 2010 at 9:31 AM, Dave Smith wrote:

>>

>>

>> I'm not sure how BigDecimal works. By the name, I would assume it

>> implements decimal floating-point arithmetic in software.

>>

>

>

Mon, 2010-04-05, 19:47

#15
Re: 0.4 * 0.4 is not 0.16, why? (is this a bug?)

Thanks for the info.

And I agree, rationals are another interesting option. I don't know about BigInts, but you can get really great performance using a Rational class with primitive ints. I understand there is an example in the "Programming in Scala" book.

Imho, in most applications that require fractional arithmetic, the BigDecimal is a bit of an overkill. Most application that do arithmetic fall into two categories: financial applications, and statistical/scientific applications.

Statistical and scientific application are well suited to native binary floating-point because they tend to require massively-iterative calculations. Hardware floating-point calculations are faster than software floating or fixed calculations, and they are accurate (they just don't have predictable rounding). They may require extremely large or extremely small values, but double precision floating-points (10^-308 to 10^308), with accuracy to 16 decimal digits are usually more than enough.

Financial applications do not require "Big" anything. In most world currencies, values between 10^-12 and 10^12 are as accurate as you need to get. For these applications, one should be concerned with predictable evaluation after rounding. What that means is calculations preserve as many "decimal" digits as possible between calculations, and that rounding is done in a way the preserves decimal digits. Beyond this, performance is the only concern. Seems to me that a Rational number implementation with primitive integers would fit the bill.

--DS

On 5 April 2010 13:26, James Iry <jamesiry [at] gmail [dot] com> wrote:

And I agree, rationals are another interesting option. I don't know about BigInts, but you can get really great performance using a Rational class with primitive ints. I understand there is an example in the "Programming in Scala" book.

Imho, in most applications that require fractional arithmetic, the BigDecimal is a bit of an overkill. Most application that do arithmetic fall into two categories: financial applications, and statistical/scientific applications.

Statistical and scientific application are well suited to native binary floating-point because they tend to require massively-iterative calculations. Hardware floating-point calculations are faster than software floating or fixed calculations, and they are accurate (they just don't have predictable rounding). They may require extremely large or extremely small values, but double precision floating-points (10^-308 to 10^308), with accuracy to 16 decimal digits are usually more than enough.

Financial applications do not require "Big" anything. In most world currencies, values between 10^-12 and 10^12 are as accurate as you need to get. For these applications, one should be concerned with predictable evaluation after rounding. What that means is calculations preserve as many "decimal" digits as possible between calculations, and that rounding is done in a way the preserves decimal digits. Beyond this, performance is the only concern. Seems to me that a Rational number implementation with primitive integers would fit the bill.

--DS

On 5 April 2010 13:26, James Iry <jamesiry [at] gmail [dot] com> wrote:

g point number which has a fixed number of bits, BigDecimal is a bignum meaning the size of possible numbers is limited only by memory (or other similar JVM limitations like object handles). And frankly, if we're going to pay that price, I'd rather have a BigRational (a pair of BigInts) than BigDecimal which can't even represent 1/3 exactly.

Mon, 2010-04-05, 20:57

#16
Re: 0.4 * 0.4 is not 0.16, why? (is this a bug?)

On Mon, Apr 5, 2010 at 1:45 PM, Brian Maso <brian [at] blumenfeld-maso [dot] com> wrote:

a/b + c/d = (a*d + b*c) / b*d

(three multiplications and one addition), while

a/b * c/d = a*c / (b*d)

(two multiplications, no addition).

Also, if they store things in reduced form, they can compute gcd(a,d) and gcd(b,c) for multiplication--which is on smaller numbers--while in the latter case, they have to finish the entire computation and then do gcd(a*d+b*c , b*d). gcd algorithms are pretty slow, and are definitely superlinear, so the latter computation is a lot more work.

--Rex

Clojure uses a Ratio class for arbitrary-precision math -- which IIt cannot help but be more expensive because

think is probably the same concept as James' "BigRational" -- just two

BigIntegers: numerator and denominator. Weird performance

characteristics though, since addition can be way more expensive than

multiplication with Ratios.

a/b + c/d = (a*d + b*c) / b*d

(three multiplications and one addition), while

a/b * c/d = a*c / (b*d)

(two multiplications, no addition).

Also, if they store things in reduced form, they can compute gcd(a,d) and gcd(b,c) for multiplication--which is on smaller numbers--while in the latter case, they have to finish the entire computation and then do gcd(a*d+b*c , b*d). gcd algorithms are pretty slow, and are definitely superlinear, so the latter computation is a lot more work.

--Rex

Mon, 2010-04-05, 21:07

#17
Re: 0.4 * 0.4 is not 0.16, why? (is this a bug?)

> Financial applications do not require "Big" anything. In most world

> currencies, values between 10^-12 and 10^12 are as accurate as you need to

> get. For these applications, one should be concerned with predictable

> evaluation after rounding. What that means is calculations preserve as

> many

> "decimal" digits as possible between calculations, and that rounding is

> done

> in a way the preserves decimal digits. Beyond this, performance is the

> only

> concern.

In reality, floating point arithmetic have some issues, which force use

decimal arithmetic in finance domain.

See http://speleotrove.com/decimal/decifaq1.html#inexact

>

>

>

> --DS

>

>

> On 5 April 2010 13:26, James Iry wrote:

>

>> g point number which has a fixed number of bits, BigDecimal is a bignum

>> meaning the size of possible numbers is limited only by memory (or other

>> similar JVM limitations like object handles). And frankly, if we're

>> going to

>> pay that price, I'd rather have a BigRational (a pair of BigInts) than

>> BigDecimal which can't even represent 1/3 exactly.

>

Mon, 2010-04-05, 21:17

#18
Re: 0.4 * 0.4 is not 0.16, why? (is this a bug?)

This was exactly the point I was making -- "we should not use binary floating point for financial" (and I have read speleotrove extensively in the past). If you go back and read the thread carefully, we are discussing the merits of decimal vs rationals as an alternative.

--DS

2010/4/5 Ruslan Shevchenko <rssh [at] gradsoft [dot] com [dot] ua>

floating point arithmetic have some issues, which force use

decimal arithmetic in financ

Mon, 2010-04-05, 23:07

#19
Re: 0.4 * 0.4 is not 0.16, why? (is this a bug?)

> This was exactly the point I was making -- "we should not use binary

> floating point for financial" (and I have read speleotrove extensively in

> the past). If you go back and read the thread carefully, we are

> discussing

> the merits of decimal vs rationals as an alternative.

>

Ok, may be I miss something.

Note, that mathematically precise figures (such as rationals) in some

situations will be incorrect from accounting point of view.

//for example you can't have exactly 100/3 euros on you bank account

(It's because accounting rules have been formed before computers)

So, for storing numbers using decimal is more natural. For calculations,

using rational arithmetic is possible, but in some cases we need emulate

accounting rules (such as banker's rounding) which are not very natural

for rational arithmetic.

> --DS

>

>

> 2010/4/5 Ruslan Shevchenko

>

>> floating point arithmetic have some issues, which force use

>> decimal arithmetic in financ

>>

>

Tue, 2010-04-06, 03:57

#20
Re: 0.4 * 0.4 is not 0.16, why? (is this a bug?)

Historically, the currencies that were derived from the Spanish Dollar (US Dollar, Canadian Dollar, Mexican Peso, Chinese Yuan, etc.) were better suited to binary representation than those currencies today. The Spanish dollar coin was worth 8 Spanish Reals, and was commonly known as "a piece of eight". Although the US Dollar was decimalized from it's creation, it was still common to do business in eights of a dollar throughout the Americas. In fact, right up until 2001, the NYSE valued stock in eighths of a dollar.

In hindsight, if we still used 8'ths, we wouldn't have any problems today with computer rounding errors like the ones we are discussing today.

I would disagree with you in your statement that accounting arithmetic is in some way not natural for rational arithmetic. Indeed all accounting values are rational, and I know of no accounting practice that make use of irrational number (such as pi or e).

If I'm wrong please clarify.

--DS

2010/4/5 Ruslan Shevchenko <rssh [at] gradsoft [dot] com [dot] ua>

In hindsight, if we still used 8'ths, we wouldn't have any problems today with computer rounding errors like the ones we are discussing today.

I would disagree with you in your statement that accounting arithmetic is in some way not natural for rational arithmetic. Indeed all accounting values are rational, and I know of no accounting practice that make use of irrational number (such as pi or e).

If I'm wrong please clarify.

--DS

2010/4/5 Ruslan Shevchenko <rssh [at] gradsoft [dot] com [dot] ua>

g numbers using decimal is more natural. For calculations,

using rational arithmetic is possible, but in some cases we need emulate

accounting rules (such as banker's rounding) which are not very natural

for rational

Tue, 2010-04-06, 04:17

#21
Re: 0.4 * 0.4 is not 0.16, why? (is this a bug?)

Now that I think about it, perhaps you are right that if we do multiple operations in rational form before rounding, the end result could be different than if we do that same operations in decimal form, rounding after each operation, as an accountant would do.

Good point!

--DS

2010/4/5 Ruslan Shevchenko <rssh [at] gradsoft [dot] com [dot] ua>

Good point!

--DS

2010/4/5 Ruslan Shevchenko <rssh [at] gradsoft [dot] com [dot] ua>

> This was exactly the point I was making -- "we should not use binary

> floating point for financial" (and I have read speleotrove extensively in

> the past). If you go back and read the thread carefully, we are

> discussing

> the merits of decimal vs rationals as an alternative.

>

Ok, may be I miss something.

Note, that mathematically precise figures (such as rationals) in some

situations will be incorrect from accounting point of view.

//for example you can't have exactly 100/3 euros on you bank account

(It's because accounting rules have been formed before computers)

So, for storing numbers using decimal is more natural. For calculations,

using rational arithmetic is possible, but in some cases we need emulate

accounting rules (such as banker's rounding) which are not very natural

for rational arithmetic.

> --DS

>

>

> 2010/4/5 Ruslan Shevchenko <rssh [at] gradsoft [dot] com [dot] ua>

>

>> floating point arithmetic have some issues, which force use

>> decimal arithmetic in financ

>>

>

Sun, 2010-04-11, 16:57

#22
Re: 0.4 * 0.4 is not 0.16, why? (is this a bug?)

Interesting! How far back in time does the the Spanish dollar go? There is mention of currency divisible by eight in the Talmud about 2 millennia ago.

On Mon, Apr 5, 2010 at 10:56 PM, Dave Smith <dave.smith.to@gmail.com> wrote:

On Mon, Apr 5, 2010 at 10:56 PM, Dave Smith <dave.smith.to@gmail.com> wrote:

Historically, the currencies that were derived from the Spanish Dollar (US Dollar, Canadian Dollar, Mexican Peso, Chinese Yuan, etc.) were better suited to binary representation than those currencies today. The Spanish dollar coin was worth 8 Spanish Reals, and was commonly known as "a piece of eight". Although the US Dollar was decimalized from it's creation, it was still common to do business in eights of a dollar throughout the Americas. In fact, right up until 2001, the NYSE valued stock in eighths of a dollar.

In hindsight, if we still used 8'ths, we wouldn't have any problems today with computer rounding errors like the ones we are discussing today.

I would disagree with you in your statement that accounting arithmetic is in some way not natural for rational arithmetic. Indeed all accounting values are rational, and I know of no accounting practice that make use of irrational number (such as pi or e).

If I'm wrong please clarify.

--DS

2010/4/5 Ruslan Shevchenko <rssh [at] gradsoft [dot] com [dot] ua>g numbers using decimal is more natural. For calculations,

using rational arithmetic is possible, but in some cases we need emulate

accounting rules (such as banker's rounding) which are not very natural

for rational

If you need accuracy as well as precision, then try using BigDecimal instead. It is much slower, though.

On Tue, Mar 30, 2010 at 12:52 AM, Himanshu <g [dot] himanshu [at] gmail [dot] com> wrote:

--

Daniel C. Sobral

I travel to the future all the time.