The best way to understand this problem is to consider the familiar
number "1/3," which is a quantity that cannot be precisely represented
in Base-10. It comes out as "almost 0.333333333...." (and the 3's go on
forever, for this number is never quite EXACTLY one-third).
The quantity "one-third" could be precisely represented in base-3, even
though (sigh..) (go figure...) the quantity "one-tenth" could not.
Anyhow, the problem is that "one tenth" can't be quite precisely
represented in base two, the native language of the so-called "float
decimal" (floating-point) format. There is a small amount of error,
which accumulates as the numbers are processed and gradually becomes big
enough to be significant. Or more precisely, as "a loss of significant
digits" in your answer.
The only way to -precisely- store a number like "38507.99" is to use a
different format called Binary-Coded Decimal, or BCD. In this format,
each decimal digit occupies 4 bits (which, if eight bits is a "byte,"
obviously must be a "nybble"). The number occupies an arbitrary number
of bytes. The sign of the number is represented by an additional
nybble, on the left or the right hand side. Our number might be
represented by something like: "$C0 00 38 50 79 90"
Well, that's not the ONLY precise way. Another way would be to multiply
the number by a fixed constant, or "scale," so that it becomes an
integer, say: +385,079,900. All arithmetic is done in integer mode
using equally-scaled numbers. This example has precisely 4 digits
represented to the right of the decimal, and the rightmost two of those
digits should be considered garbage. But a "dollars and cents" quantity
(2 digits) would be represented here in a consistent way -- and if the
rightmost two of the four digits are thrown away, the "rounding" effect
that remains in the leftmost two digits (the cents) will be consistent.
This is how systems like Microsoft Access implement their "currency"
data type. (But it's not how Delphi does it.)
Quote
>Duncan Murdoch wrote:
> On Tue, 9 May 2000 11:23:00 -0400, "Bruce Roberts"
> <no.junk.please....@attcanada.net> wrote:
> >When I first saw this post I immediately assumed that it was simply a
> >rounding error induced problem... However
> > s := '38507.99';
> > f := 100 * StrToFloat (s);
> > edit1.text := format ('%e', [f]);
> >displays 3.85079900000000E+006, while
> > f := trunc (100 * StrToFloat (s));
> > edit2.text := format ('%e', [f]);
> >displays 3.85079800000000E+006. These results are the same for f as real,
> >single, double, and extended. I also wondered if the '100 *' was introduce a
> >REAL intermediate and replaced it with an extended variable.
> It's a rounding problem. The value 38507.99 can't be stored in real,
> single, double or extended, so when you multiply by 100, you don't get
> 3850799. Take a look at the bit pattern in the floating point unit
> and you'll see exactly what gets stored instead.
> Duncan Murdoch
--
------------------------------------------------------------------
Sundial Services :: Scottsdale, AZ (USA) :: (480) 946-8259
mailto:i...@sundialservices.com (PGP public key available.)
Quote
> Fast(!), automatic table-repair with two clicks of the mouse!
> ChimneySweep(R): "Click click, it's fixed!" {tm}
> http://www.sundialservices.com/products/chimneysweep