Gentoo Archives: gentoo-user

From: Franz Fellner <alpine.art.de@×××××.com>
To: hw <hw@×××××××××××××××××××××.de>
Cc: gentoo-user@l.g.o
Subject: Re: [gentoo-user] 69.99 != 69.99
Date: Sat, 22 Aug 2015 15:20:38
Message-Id: 20150822172138.GG22870@TP_L520.localdomain
In Reply to: Re: [gentoo-user] 69.99 != 69.99 by hw
1 On Sat, 22 Aug 2015 16:57:41 +0200, hw <hw@×××××××××××××××××××××.de> wrote:
2 >
3 >
4 > Am 22.08.2015 um 15:43 schrieb Alan McKinnon:
5 > > On 22/08/2015 15:26, hw wrote:
6 > >>
7 > >> Hi,
8 > >>
9 > >> I have the following in a perl script:
10 > >>
11 > >>
12 > >> if ($a != $b) {
13 > >> print "e: '$a', t: '$b'\n";
14 > >> }
15 > >>
16 > >>
17 > >> That will print:
18 > >>
19 > >> e: '69.99', t: '69.99'
20 > >>
21 > >>
22 > >> When I replace != with ne (if ($a ne $a) {), it doesn't print.
23 > >>
24 > >>
25 > >> Is that a bug or a feature? And if it's a feature, what's the explanation?
26 > >>
27 > >> And how do you deal with comparisions of variables when you get randomly
28 > >> either correct results or wrong ones? It's randomly because this
29 > >> statement checks multiple values in the script, and 69.99 is the only
30 > >> number showing up yet which isn't numerically equal to itself (but equal
31 > >> to itself when compared as strings).
32 > >
33 > >
34 > >
35 > > Computer languages have a much more exact idea of what equality means
36 > > than you do. In your head (because you are human, not silicon) you are
37 > > completely comfortable with taking "69.99" and treat8ing it as a string,
38 > > or a number, or a mostly-rounded-off floating point number.
39 > >
40 > > The computer does not do it like that. To a computer, the same must be
41 > > exactly the same. Two things a little bit different are completely
42 > > different (or not equal). And perl has two different operators for
43 > > (in)equality:
44 > >
45 > > != does a numerical comparison. More on this below
46 > > ne does a string comparison. When viewed as a bunch of characters, 69.99
47 > > and 69.99 are identical.
48 >
49 > When the value is numerically not 69.99 but something like 69.99001,
50 > then printing the value should print 69.99001 rather than 69.99.
51
52 To take your perl statement:
53 perl -e 'printf("%34.32f\n", 23.33*3)'
54 69.98999999999999488409230252727866
55
56 It doesnt print that strange value because it rounds it to something
57 "more readable", as the value is known to be not as precise.
58
59 >
60 > perl -e 'print 1/3 . "\n";' prints 0.333333333333333
61 >
62 > perl -e 'printf("%34.32f\n", 1/3);' prints
63 > 0.33333333333333331482961625624739
64 >
65 > perl -e 'print (((1/3 == 0.333333333333333) ? "equal" : "not equal") .
66 > "\n");' prints "not equal"
67 >
68 > perl -e 'print (((1/3 == 0.0.33333333333333331482961625624739) ? "equal"
69 > : "not equal") . "\n");' prints "Integer overflow in decimal number at
70 > -e line 1." a couple times
71
72 typo ;)
73 1/3 == 0.0.333[...]
74 Here it prints "equal".
75
76 >
77 > This is random, may it be predictable or not, and what's the integer here?
78 >
79 > > Now, your comparisons are NOT random. They are entirely predictable, as
80 > > long as you know what is going on; you are running into floating point
81 > > numbers. And as it turns out, computers never represent these things
82 > > exactly (they are NOT integers). Even though they look identical
83 > > on-screen, in RAM they will not be (this must be so for perl to do the
84 > > print). Maybe they actually resolve to 69.990000001 and 69.99000000. You
85 > > see them as close-as-dammit equal, perl sees them as entirely different.
86 >
87 > Why can't it print the number as it is, or at least as it is compared,
88 > like it should? If it would, one could see at once what the problem is.
89 >
90 > > This is such as huge IT problem that many solutions have been proposed.
91 > > You get classes like BigFloat that represent a floating point as an
92 > > integer so that equality works, you can round the floats off before
93 > > comparing them, or just make the things integers.
94 > >
95 > > The last one is nice: don't represent money as dollars and cents,
96 > > represent it as cents or decicents and only divide by 100 (or 1000) when
97 > > you finally get to display it.
98 >
99 > That would add quite a lot of complexity, and the problem should either
100 > be handled transparently, or the value should be printed as the
101 > software/computer sees it. It is a recipe for disaster when you tell
102 > your computer to print something but it prints something else instead.
103 >
104 > > So how to fix your problem: you are doing what you shouldn't do - trying
105 > > equality on floats. Turn them into integers, or round them off, or use
106 > >> =/<= instead of !=
107 >
108 > '=/<=' is not an operator in perl?
109 >