On 22/08/2015 15:26, hw wrote:
> 
> Hi,
> 
> I have the following in a perl script:
> 
> 
>       if ($a != $b) {
>         print "e: '$a', t: '$b'\n";
>       }
> 
> 
> That will print:
> 
> e: '69.99', t: '69.99'
> 
> 
> When I replace != with ne (if ($a ne $a) {), it doesn't print.
> 
> 
> Is that a bug or a feature?  And if it's a feature, what's the explanation?
> 
> And how do you deal with comparisions of variables when you get randomly
> either correct results or wrong ones?  It's randomly because this
> statement checks multiple values in the script, and 69.99 is the only
> number showing up yet which isn't numerically equal to itself (but equal
> to itself when compared as strings).



Computer languages have a much more exact idea of what equality means
than you do. In your head (because you are human, not silicon) you are
completely comfortable with taking "69.99" and treat8ing it as a string,
or a number, or a mostly-rounded-off floating point number.

The computer does not do it like that. To a computer, the same must be
exactly the same. Two things a little bit different are completely
different (or not equal). And perl has two different operators for
(in)equality:

!= does a numerical comparison. More on this below
ne does a string comparison. When viewed as a bunch of characters, 69.99
and 69.99 are identical.

Now, your comparisons are NOT random. They are entirely predictable, as
long as you know what is going on; you are running into floating point
numbers. And as it turns out, computers never represent these things
exactly (they are NOT integers). Even though they look identical
on-screen, in RAM they will not be (this must be so for perl to do the
print). Maybe they actually resolve to 69.990000001 and 69.99000000. You
see them as close-as-dammit equal, perl sees them as entirely different.

This is such as huge IT problem that many solutions have been proposed.
You get classes like BigFloat that represent a floating point as an
integer so that equality works, you can round the floats off before
comparing them, or just make the things integers.

The last one is nice: don't represent money as dollars and cents,
represent it as cents or decicents and only divide by 100 (or 1000) when
you finally get to display it.

So how to fix your problem: you are doing what you shouldn't do - trying
equality on floats. Turn them into integers, or round them off, or use
>=/<= instead of !=


-- 
Alan McKinnon
alan.mckin...@gmail.com


Reply via email to