Because sqrt(x) * sqrt(x) is distinct to x

62 Views Asked by At

The next code sqrt(x) and sqrt(x) * sqrt(x) ist distinc to x, becouse?

I'm using boost to handle large numbers but the square of the root is different from the original number and that worries me, do you know how I could get the original number x?

#include<iostream>
#include <boost/multiprecision/cpp_int.hpp>
using namespace boost::multiprecision;

using namespace std;


int main() {
   boost::multiprecision::cpp_int num= 7459874565236544789;

   
   boost::multiprecision::cpp_int num_sqrt= sqrt(num);
   boost::multiprecision::cpp_int num_sqrt_square= num_sqrt*num_sqrt;

    

   cout <<  "\n num: " << num <<
            "\n num_sqrt: " << num_sqrt <<
            "\n num_sqrt_square: " << num_sqrt_square <<
            "\n _num_sqrt_square: " << sqrt(num) * sqrt(num);
}



I expect that sqrt(x) * sqrt(x) = x, but the output:

num: 7459874565236544789
num_sqrt: 2731277094
num_sqrt_square: 7459874564209084836
_num_sqrt_square: 7459874564209084836

num != num_sqrt_square  !!!

Output, num distinct to square root

2

There are 2 best solutions below

0
AudioBubble On

The square root of a non-perfect square is an irrational number, so it is not possible to represent it finitely and √x √x = x can't be achieved exactly.

As a workaround, you can perform the comparison with a relative tolerance.


In general, in such situations it is simpler to keep the original value and use the square root only where essential.

0
njuffa On

The assumption that the square of sqrt(x) == x does not hold with any finite-precision floating-point format by the pigeonhole principle, since the square root is a contracting operation. Take any of the IEEE-754 binary floating-point format for example. The number of available discrete encodings for each binade is the same. So there are as many encodings available for [1, 2) as there are for [2, 4).

In other words, there are twice as many encodings available for [1, 4) as there are for [1, 2). If we apply the square root to all encodings in [1, 4), the interval [1, 4) is mapped to the interval [1, 2), but there are only half as many encodings available for the target interval as there are for the source interval. By the pigeonhole principle there will therefore be "collisions" where two source arguments map to the same result. As a consequence, subsequent squaring can restore the original argument only for some inputs.

With IEEE-754 floating-point arithmetic, perfect round-trip behavior may hold when first applying an expanding operation followed by the corresponding contracting operation. That is, sqrt (x * x) == |x|, as proven in

Sylvie Boldo, "Stupid is as Stupid Does: Taking the Square Root of the Square of a Floating-Point Number", Electronic Notes in Theoretical Computer Science 317 (2015) 27–32.