Hacksaw wrote:
>
> > now, a stupid solution is:
> >
> > for (my $value = -1000; $value <= 1000; $value += 100) {
> >         print $value/1000, "\n";
> > }
> >
> > hehe,
> >
>
> Sadly, it's not as stupid as you think. Unless I misunderstand things, what
> you are seeing here is a problem called IEEE 754 floating point.
>
> I'm sure there is some explanation that someone could offer as to why it's the
> "best" thing, but IEEE754 doesn't represent simple decimals very well. It
> converts them into binary using an odd method allowing it to represent the
> number in one chunk, avoiding the mantissa and exponent form.
>
> However, this encoding can't represent any decimal not ending in 5 finitely,
> much the same way it's not possible to represent 1/3 in decimal finitely.
>
> The upshot of this is that unless you *really* need floating point math, and
> are willing to do what is necessary to compensate for the error that will
> creep in, you should stay away from it.
>
> Smart folks will often represent monetary values in hundreths or thousanths of
> cents, just to avoid floating point math.

It's also worth pointing out here that rational values are almost always what is
wanted in this sort of situation.

The (very nice indeed) Math::Fraction module lets you do just this. The only
changes to the code are to initialise $value as a Math::Fraction object with

  my $value = frac -1

and to convert the value back to decimal for printing (otherwise
the values would appear as ".. 1/10 1/5 3/10 .." etc.).

HTH,

Rob

  use strict;
  use warnings;

  use Math::Fraction;

  for (my $value = frac -1; $value <= 1; $value += 0.1) {
    print $value->decimal, "\n";
  }

**OUTPUT

  -1
  -0.9
  -0.8
  -0.7
  -0.6
  -0.5
  -0.4
  -0.3
  -0.2
  -0.1
  0
  0.1
  0.2
  0.3
  0.4
  0.5
  0.6
  0.7
  0.8
  0.9
  1



-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>


Reply via email to