This question already has an answer here:
- Floating point error in representation? 2 answers
Why the result of multiplication 0.3 and 3 is 0.89999999999999 in Scala?
This question already has an answer here:
Why the result of multiplication 0.3 and 3 is 0.89999999999999 in Scala?
Floating point calculation is reasonably complex subject.
This has to do with the binary representation of a floating point number, that doesn't guarantee every possible number (obviously), to have an exact representation, which can lead to errors in operations, and yes, these errors can propagate.
Here is a link on the subject, although it isn't the simplest thing out there, it can get you a good perspective if you want to understand the subject.
http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
The bottom line problem is that for a given floating point number, a rational, it is possible that the binary representation of that number needs more precision than what's available in the given language.
For instance, if you use 24 bits to store a double, but the binary representation of your floating point value needs 25 bits to be represented accurately, there will be a rounding error.
Edit:
As Péter Török noted in the comment, most known programming languages use the same representations for common data types, float
-> 32 bits, double
-> 64 bits, so the precision can usually be calculated taking the data type into regard, no matter the language.
That is not only the case in Scala, but in any language/platform, that uses the IEEE standard for floating point numbers.
Example in ruby:
0.1.9.2p320 :001 > 0.3 * 3
=> 0.8999999999999999
or Python:
>>> 0.3 * 3
0.8999999999999999
This has almost nothing to do with Scala!
The reason is to do with how computers represent floating point numbers. Computers use a binary representation, rather than a decimal one, so numbers such as 0.3 are not represented as that precisely but using an approximation that can be succinctly expressed in base 2. The result of this is that operations performed on these numbers may be slightly out from what you expect the answer to be. For more detail, see Floating Point.
You can get around this if necessary by implementing something like a Fraction
class, which uses its own arithmetic to perform these computations exactly.
Use BigDecimal if you want exact values.
BigDecimal(3)*0.3
Will give you 0.9
That is a side-effect of the commonly used floating point values representation.
I often encoutenred that problem and make a simple function that "rounds" the number to the nearest bigger-than-desired-precision value. It goes in C as:
int64_t __pow10_arr[18] = { 1l, 10l, 100l, 1000l, 10000l, 100000l,
1000000l, 10000000, 100000000l, 1000000000l, 10000000000l, 100000000000l,
1000000000000l, 10000000000000l, 100000000000000l, 1000000000000000l, 10000000000000000l, 100000000000000000l };
double roundToNfractions ( double val, uint8_t n )
{
val *= __pow10_arr[n];
val += 0.5;
val = (uint64_t) val;
val /= __pow10_arr[n];
return val;
}
Not very efficient but does the trick, because you can safely write
printf("%.2d", val);
and you always get results like 3.00
instead of 2.99
;