Reputation: 159
long mynum = Long.parseLong("7660142319573120");
long ans = (long)Math.sqrt(mynum) // output = 87522239
long ans_ans = ans * ans;
In this case, I am getting ans_ans > mynum where it should be <=mynum. Why such behavior? I tried this with node js as well. There also result is same.
Upvotes: 2
Views: 3603
Reputation: 540
double ans = (double)Math.sqrt(15);
System.out.println("Double : " + ans);
double ans_ans = ans * ans;
System.out.println("Double : " + ans_ans);
long ans1 = (long)Math.sqrt(15);
System.out.println("Long : " + ans1);
long ans_ans1 = ans1 * ans1;
System.out.println("Long : " + ans_ans1);
Results :
Double : 3.872983346207417
Double : 15.000000000000002
Long : 3
Long : 9
I hope this makes it clear.
Upvotes: 3
Reputation: 25992
You do not need the long type, all numbers are representable in double
, and Math.sqrt
first converts to double then computes the square root via FPU instruction (on a standard PC).
This situation occurs for numbers b=a^2-1
where a
is an integer in the range
67108865 <= a <= 94906265
The square root of b
has a series expansion starting with
a-1/(2*a)-1/(8*a^2)+...
If the relative error 1/(2*a^2)
falls below the machine epsilon, the closest representable double
number is a
.
On the other hand for this trick to work one needs that a*a-1.0
is exactly representable in double
, which gives the conditions
1/(2*a^2) <mu=2^(-53) < 1/(a^2)
or
2^52 < a^2 < 2^53
2^26+1=67108865 <= a <= floor(sqrt(2)*2^26)=94906265
Upvotes: 1
Reputation: 1486
You are calling Math.sqrt
with a long.
As the JavaDoc points out, it returns a "correctly rounded value".
Since your square-root is not an non-comma-value (87522238,999999994
), your result is rounded up to your output 87522239
.
After that, the square of the value is intuitively larger than mynum
, since you multiply larger numbers than the root!
Upvotes: 4
Reputation: 181745
Math.sqrt
operates on double
s, not long
s, so mynum
gets converted to a double
first. This is a 64-bits floating point number, which has "15–17 decimal digits of precision" (Wikipedia).
Your input number has 16 digits, so you may be losing precision on the input already. You may also be losing precision on the output.
If you really need an integer square root of long
numbers, or generally numbers that are too big for accurate representation as a double
, look into integer square root algorithms.
You can also use LongMath.sqrt()
from the Guava library.
Upvotes: 5
Reputation: 125
The answer is: rounding.
The result of (Long)Math.sqrt(7660142319573120)
is 87522239
, but the mathematical result is 87522238,999999994287166259537761...
.
if you multiply the ans
value, which is rounded up in order to be stored as a whole number, you will get bigger number than multiplying the exact result.
Upvotes: 2