Gentoo Archives: gentoo-user

From: Alan McKinnon <alan.mckinnon@×××××.com>
To: gentoo-user@l.g.o
Subject: Re: [gentoo-user] 69.99 != 69.99
Date: Sat, 22 Aug 2015 13:43:39
Message-Id: 55D87C7B.8060700@gmail.com
In Reply to: [gentoo-user] 69.99 != 69.99 by hw
1 On 22/08/2015 15:26, hw wrote:
2 >
3 > Hi,
4 >
5 > I have the following in a perl script:
6 >
7 >
8 > if ($a != $b) {
9 > print "e: '$a', t: '$b'\n";
10 > }
11 >
12 >
13 > That will print:
14 >
15 > e: '69.99', t: '69.99'
16 >
17 >
18 > When I replace != with ne (if ($a ne $a) {), it doesn't print.
19 >
20 >
21 > Is that a bug or a feature? And if it's a feature, what's the explanation?
22 >
23 > And how do you deal with comparisions of variables when you get randomly
24 > either correct results or wrong ones? It's randomly because this
25 > statement checks multiple values in the script, and 69.99 is the only
26 > number showing up yet which isn't numerically equal to itself (but equal
27 > to itself when compared as strings).
28
29
30
31 Computer languages have a much more exact idea of what equality means
32 than you do. In your head (because you are human, not silicon) you are
33 completely comfortable with taking "69.99" and treat8ing it as a string,
34 or a number, or a mostly-rounded-off floating point number.
35
36 The computer does not do it like that. To a computer, the same must be
37 exactly the same. Two things a little bit different are completely
38 different (or not equal). And perl has two different operators for
39 (in)equality:
40
41 != does a numerical comparison. More on this below
42 ne does a string comparison. When viewed as a bunch of characters, 69.99
43 and 69.99 are identical.
44
45 Now, your comparisons are NOT random. They are entirely predictable, as
46 long as you know what is going on; you are running into floating point
47 numbers. And as it turns out, computers never represent these things
48 exactly (they are NOT integers). Even though they look identical
49 on-screen, in RAM they will not be (this must be so for perl to do the
50 print). Maybe they actually resolve to 69.990000001 and 69.99000000. You
51 see them as close-as-dammit equal, perl sees them as entirely different.
52
53 This is such as huge IT problem that many solutions have been proposed.
54 You get classes like BigFloat that represent a floating point as an
55 integer so that equality works, you can round the floats off before
56 comparing them, or just make the things integers.
57
58 The last one is nice: don't represent money as dollars and cents,
59 represent it as cents or decicents and only divide by 100 (or 1000) when
60 you finally get to display it.
61
62 So how to fix your problem: you are doing what you shouldn't do - trying
63 equality on floats. Turn them into integers, or round them off, or use
64 >=/<= instead of !=
65
66
67 --
68 Alan McKinnon
69 alan.mckinnon@×××××.com

Replies

Subject Author
Re: [gentoo-user] 69.99 != 69.99 hw <hw@×××××××××××××××××××××.de>