Re: FAQ 4.2 Why is int() broken?
- From: "Peter J. Holzer" <hjp-usenet2@xxxxxx>
- Date: Mon, 28 Jul 2008 23:44:06 +0200
On 2008-07-28 17:56, szr <szrRE@xxxxxxxxxxxxxxx> wrote:
Peter J. Holzer wrote:<--><--><--><--><--><--><--><--><--><--><--><-->
On 2008-07-28 06:12, Jürgen Exner <jurgenex@xxxxxxxxxxx> wrote:
"szr" <szrRE@xxxxxxxxxxxxxxx> wrote:
Peter J. Holzer wrote:
Please get it into your head that extra precision *does* *not*
solve this problem. To express 1/10 in binary you need an infinite
number of digits, just like you need an infinite number of digits
to express 1/3 in decimal.
Maybe you meant to write something else, as 1/10 is 0.1 and does not
require an infinite number of digits;
Yes, it does.
It doesn't, but I didn't write that. I wrote it takes an infinite
number of *binary* digits.
In binary, 1/10 is 0.00011001100110011...
For some reason I thought that applied to decimal expresses that
repeated infinately, like 1/3 => .3333..., not decimals with a fixed
number of dibits, which 1/0 => 0.1 is:
$ perl -e 'my $x = 1/10; print unpack("b64", pack("d", $x)), "\n"'
0101100110011001100110011001100110011001100110011001110111111100
Um, the repeating pattern is clearly visible here. The pattern is
broken on the left side because of rounding (you printed the pattern in
little endian, so the least significant digit is on the left and the,
er, binary point is just to the right of the rightmost ">" I made).
$ perl -e 'my $x = 1/2; print unpack("b64", pack("d", $x)), "\n"'
0000000000000000000000000000000000000000000000000000011111111100
$ perl -e 'my $x = 1/4; print unpack("b64", pack("d", $x)), "\n"'
0000000000000000000000000000000000000000000000000000101111111100
$ perl -e 'my $x = 1/8; print unpack("b64", pack("d", $x)), "\n"'
0000000000000000000000000000000000000000000000000000001111111100
1/2, 1/4, 1/8 are all exactly representable in binary, because they are
integral multiples of powers of two. 1/10 is not, because it is not an
integral multiple of powers of two. 1/3 is not representable in decimal
because it is not an integral multiple of a power of 10. And 1/2 is not
representable in base-15 because it is not an integral multiple of a
power of 15 (but 1/3 and 1/5 are). For any given base, there are always
only a small (but infinite :-)) number of fraction which are
representable in that base.
it needs just one decimal digit
Irrelevant because your typical computer does not use decimal numbers
but binary numbers, just like Peter said.
Actually, I didn't write what "a typical computer" uses, just what
happens when a binary system is used (which is what perl uses on most
(all?) platforms - COBOL uses normally uses decimal).
Even among different types of computers floating point calculations are
not all done the same. For instance, I have a graphing calculator, which
is essentially tiny computer with a 6 MHz cpu and yet it can do many
floating point calculations more accurately than my dual core cpu
desktop.
I'm not up to date with calculators (the last one I bought was an HP-48
20 years ago), but frankly, I doubt that it is more accurate. It has
probably less than 15 digits of mantissa. It probably does its
computations in decimal, which makes them even less accurate, but the
errors *match* *your* *expectations*, so you don't notice then.
Granted, it's a calculator, but I have often wondered why it
seems to be able to handle such calculations better than a CPU that's
over 400 times faster.
Different target. Calculators can be slow - they do only primitive
computations, and if they finish them in a short but noticable time its
still "fast enough". A modern CPU is supposed to be able to do hundreds
of millions such computations per second. Calculators are also rarely
used for computations where accuracy is much of an issue - 8 or 12
digits are enough. But they are used by people who expect 0.1 * 10 to be
1.0 but aren't overly surprised if 1/3*3 is 0.9999999.
In short it is able to "handle such calculations" because it has been
designed to do so. Floating point hardware has been designed to give the
most accurate result in a very short time. You can always implement
decimal arithmetic yourself or use a library[1] - it will still be a lot
faster than your calculator.
hp
[1] Incidentally, I know of one modern processor (the IBM Power6) which
implements full decimal floating point arithmetic in hardware.
.
- References:
- FAQ 4.2 Why is int() broken?
- From: PerlFAQ Server
- Re: FAQ 4.2 Why is int() broken?
- From: szr
- Re: FAQ 4.2 Why is int() broken?
- From: Peter J. Holzer
- Re: FAQ 4.2 Why is int() broken?
- From: szr
- Re: FAQ 4.2 Why is int() broken?
- From: Peter J. Holzer
- Re: FAQ 4.2 Why is int() broken?
- From: szr
- Re: FAQ 4.2 Why is int() broken?
- From: Peter J. Holzer
- Re: FAQ 4.2 Why is int() broken?
- From: szr
- Re: FAQ 4.2 Why is int() broken?
- From: Jürgen Exner
- Re: FAQ 4.2 Why is int() broken?
- From: Peter J. Holzer
- Re: FAQ 4.2 Why is int() broken?
- From: szr
- FAQ 4.2 Why is int() broken?
- Prev by Date: Re: Perl - approach to query https website for code & parsing xml response
- Next by Date: Re: Can I upload Perl program in unicode?
- Previous by thread: Re: FAQ 4.2 Why is int() broken?
- Next by thread: Re: FAQ 4.2 Why is int() broken?
- Index(es):
Relevant Pages
|