Why isn't 2 equal to √2 * √2?

2k views Asked by At

I noticed that according to Lua, 2 ~= math.sqrt(2) ^ 2

print(2 == math.sqrt(2) ^ 2) --> false
print(2, math.sqrt(2) ^ 2) --> 2  2

Why is this happening?

3

There are 3 answers

4
Yu Hao On BEST ANSWER

Most floating point numbers can't be stored precisely in Lua's number type (C's double by default). math.sqrt(2) is one of them.

If you try:

print(2 - math.sqrt(2) ^ 2)

Output: -4.4408920985006e-016 which is a very small number, but still, making the two numbers not exactly equivalent.


This floating point precision problem exists not only in Lua, but also in many other languages. As @Thilo comments, you can use a small "delta" when comparing for equality in practice. You might be interested in: C FAQ: What's a good way to check for ``close enough'' floating-point equality?.

1
Tom Blodget On

The nature of floating-point arithmetic is very important in general programming environments. Classic C static source code analysis programs (e.g., "lint") will actually give you a warning if you use relational operators on floating-point numbers. As other have said, usa a tolerance in comparisons.

However, the example you chose, √2, is irrational. No calculating number system can hold that number. It can only be exact as a symbolic expression. There are a few symbolic programming systems available: Octave-Symbolic, MathCAD, MATLAB, ... and now Wolfram (I think). They will keep √2 as a expression and evaluate √2 * √2 as exactly 2.

0
njuffa On

The following reasoning shows that in general it is not possible for sqrt(x)*sqrt(x) == x to hold for all operands in floating-point arithmetic, whether it be binary or decimal, even if the square root operation returns correctly rounded results (as is typically the case on modern computers that are compliant with the IEEE-754 floating-point standard).

In a finite-precision binary floating point representation, each binade (the space between two successive powers of 2) comprises the same count of exactly representable numbers. For IEEE-754 single precision, there are 223 of these machine numbers per binade, for IEEE-754 double precision there are 252 such numbers per binade.

Square root is a contracting operation, in that it maps an input domain of two binades, say [1,4), to a result range of only one binade, say [1,2). So in the case of IEEE-754 double-precision operands, 253 possible function arguments across two binades are mapped to at most 252 different square root results. If we now square the results of the square root operation, we wind up with at most 252 different products spread out over two binades able to represent 253 machine numbers.

Therefore, the equality sqrt(x)*sqrt(x) == x can hold for at most half of the possible floating-point inputs. Experimentally one can show that it holds for exactly half of the inputs from the two binades.

On the other hand, the equality x == sqrt (x * x) does hold in IEEE-754 floating-point arithmetic, provided there is no intermediate overflow or underflow in the computation of the product.