2
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.

2
  • 3
    You can write long mynum = 7660142319573120L; instead of using parseLong. Not related to question, just general remark. Commented Feb 16, 2017 at 8:07
  • Thank you very much for the suggestion Commented Feb 16, 2017 at 11:29

5 Answers 5

5

Math.sqrt operates on doubles, not longs, 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.

Sign up to request clarification or add additional context in comments.

Comments

4

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!

5 Comments

If it is rounding then answer of Math.sqrt(15) should be 4 as it is 3.872983346207417
@AbhilashMandaliya yes, that's right, the result of Math.sqrt() is double, but in your example it's casted to long: (long)Math.sqrt(mynum) so it's automatically rounded. try Math.sqrt(15) and (long)Math.sqrt(15) to see the difference
It comes 3 only as @IfOnly has mentioned below
@AbhilashMandaliya normally casting to long gives you a number truncated towards zero, but in your case from the example with mynum, it was too big to be stored in a double, I suppose
@AbhilashMandaliya: There are two places where the sqrt value is being modified. (1) The Math.sqrt call rounds the true mathematical result to the nearest representable double. (2) The conversion of that double to long truncates rather than rounds. In your particular case, it just so happens that the rounding of the Math.sqrt result takes you from something just under an integer up to exactly that integer. As @Lutz explains in his (IMO excellent) answer, this is quite unusual, and only happens for a handful of exactly representable integers.
3
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.

1 Comment

Please provide some explanation for your answer. Brevity is acceptable, but fuller explanations are better. how-to-answer-guide
2

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.

1 Comment

If it is rounding then answer of Math.sqrt(15) should be 4 as it is 3.872983346207417
1

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 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.