I'm not sure, but I think it's not really about cutting off the digits (although that's the effect it has). At least with python, I think what happens is:
* repr gives you the decimal number with the exact value of the floating-point number, i.e. 0.30000000000000004
* print gives you the least-precise decimal number whose closest floating-point representation is equal to the floating-point number
That is, there are (infinitely) many decimal numbers such that the closest floating-point representation has the value 0.30000000000000004. One of these decimal numbers is 0.3, and of all such decimal numbers, this has the fewest digits. So that's the one that gets printed.
I now think the behiviour I ascribed to print, is actually what repr does. I'm not sure about print, but I guess it is just rounding to a certain number of places.
>>> from decimal import Decimal
>>> Decimal(0.1+0.2)
Decimal('0.3000000000000000444089209850062616169452667236328125')
>>> Decimal(0.3)
Decimal('0.299999999999999988897769753748434595763683319091796875')
>>> Decimal(0.300000000000000000000000000001)
Decimal('0.299999999999999988897769753748434595763683319091796875')
>>> print 0.300000000000000000000000000001
0.3
>>> repr(0.300000000000000000000000000001)
'0.3'
>>> D(0.30000000000000004)
Decimal('0.3000000000000000444089209850062616169452667236328125')
>>> repr(0.299999999999999988897769753748434595763683319091796875)
'0.3'
>>> repr(0.30000000000000004)
'0.30000000000000004'
>>> print 0.30000000000000004
0.3 Python 3.5.0 (v3.5.0:374f501f4567, Sep 13 2015, 02:27:37) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from decimal import Decimal
>>> Decimal('0.1') + Decimal('0.2') - Decimal('0.3')
Decimal('0.0')
>>> Decimal(0.1) + Decimal(0.2) - Decimal(0.3)
Decimal('2.775557561565156540423631668E-17')
>>> Decimal(0.1) == Decimal('0.1')
False >>> print(0.1 + 0.2)
0.30000000000000004Do we really expect calculations on floating point numbers to be the same as calcualtions with real numbers?
The only problem I see is that often the floating point format is not specified properly. When one writes "0.3", what does it actually mean? Does the format the compiler uses internally conform to IEEE 754? Is it 32bit, 64bit, 80bit or something else?
It's perfectly well-specified. If you are using double-precision floating point, "0.3" means 0x3fd3333333333333 (as bits), or 0.299999999999999988897769753748434595763683319091796875 (as an exact number: the closest representable number to 0.3).
But why should it do so? Do all languages specify the details of how floating point input is handled by the compiler/interpreter?
That said, a lot of low-level languages don't: C doesn't guarantee this, for example. C doesn't even mandate IEEE 754, and it merely requires that "float" is a subset of the values of "double" which is itself a subset of the values of "long double".
It's amazing that someone went to the trouble to register a custom domain for this and put up a nicely formatted page, yet doesn't explain the above: that it's not (just) a matter of representation, but printing precision.
This is because Perl 6 decimal literals are stored in a built-in rational type called Rat, which internally stores numbers as ratios between integers. So that 0.1, 0.2, 0.3 are internally stored as the tuples (1,10), (2,10), and (3,10), and the decimal value you see is just the string representation and not the actual internal value.
If you want your decimal literal to be floating-point (called Num in Perl 6), you want to add e0 to the end.
To wit:
perl6 -e 'say 0.1+0.2-0.3' reveals '0'
perl6 -e 'say 0.1e0+0.2e0-0.3e0' reveals '5.55111512312578e-17'
If you'd like to flesh out the perl section a bit though, maybe include the differences between 5 and 6, I'd be happy to merge a pull request.
It's very commonly used in finance, for example.
Finance is a big domain.
One it so use fixed point decimal with a 1/100 scaling instead of floating point. So yes, integers and then you shift the decimal point when you output.
But you have to watch out for interest calculations, you might earn a fraction of a penny on a daily basis but over a year it adds up and you can't throw away that accuracy.
So you might do all math as floating point, but with pennies instead of dollars.
Or you can do Binary Coded Decimal, which stores each group of decimal number after the decimal point exactly, in many ways it similar to fixed point decimal, since it is a fixed point.
The issue with BCD would be data store support and CPU support right? Do CPUs support doing math directly with BCD values and does your DB support doing math directly with BCD values?
In any case, using floating point for any currency calculations is a huge no-no, even though a lot of things do it anyway.
I work with Magento daily and all their currency math uses PHP floats and the rounding errors drive me bonkers.
Perhaps surprisingly to some, x86 has instructions for BCD manipulation at the CPU level. Legacy.
https://books.google.ch/books?id=SPXHAgAAQBAJ&pg=PA44&lpg=PA...
>There are three binary floating-point basic formats (encoded with 32, 64 or 128 bits) and two decimal floating-point basic formats (encoded with 64 or 128 bits)
Here's an example using perl5:
perl -e 'print 0.1+0.2' yields '0.3', which looks OK, however
perl -e 'print 0.1+0.2-0.3' reveals '5.55111512312578e-17'
So, it's better to print the result of 0.1+0.2-0.3
For what its worth, perl6 passes this test with flying colours.