On Sat, 22 Aug 2015 16:57:41 +0200, hw <h...@gartencenter-vaehning.de> wrote:
> 
> 
> Am 22.08.2015 um 15:43 schrieb Alan McKinnon:
> > 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.
> 
> When the value is numerically not 69.99 but something like 69.99001, 
> then printing the value should print 69.99001 rather than 69.99.

To take your perl statement:
perl -e 'printf("%34.32f\n", 23.33*3)'
69.98999999999999488409230252727866

It doesnt print that strange value because it rounds it to something
"more readable", as the value is known to be not as precise.

> 
> perl -e 'print 1/3 . "\n";' prints 0.333333333333333
> 
> perl -e 'printf("%34.32f\n", 1/3);' prints 
> 0.33333333333333331482961625624739
> 
> perl -e 'print (((1/3 == 0.333333333333333) ? "equal" : "not equal") . 
> "\n");' prints "not equal"
> 
> perl -e 'print (((1/3 == 0.0.33333333333333331482961625624739) ? "equal" 
> : "not equal") . "\n");' prints "Integer overflow in decimal number at 
> -e line 1." a couple times

typo ;)
1/3 == 0.0.333[...]
Here it prints "equal".

> 
> This is random, may it be predictable or not, and what's the integer here?
> 
> > 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.
> 
> Why can't it print the number as it is, or at least as it is compared, 
> like it should?  If it would, one could see at once what the problem is.
> 
> > 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.
> 
> That would add quite a lot of complexity, and the problem should either 
> be handled transparently, or the value should be printed as the 
> software/computer sees it.  It is a recipe for disaster when you tell 
> your computer to print something but it prints something else instead.
> 
> > 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 !=
> 
> '=/<=' is not an operator in perl?
> 

Reply via email to