2017-02-16 122 views
1
long mynum = Long.parseLong("7660142319573120"); 
long ans = (long)Math.sqrt(mynum) // output = 87522239 
long ans_ans = ans * ans; 

在这种情况下,我得到了ans_ans> mynum,它应该是< = mynum。为什么这样的行为我也尝试过使用节点js。结果也是一样的。为什么Math.sqrt()在java中输出错误的值?

+2

你可以写'长myNum的= 7660142319573120L; '而不是使用parseLong。与问题无关,只是一般性评论。 –

+0

非常感谢您的建议 –

回答

2

答案是:四舍五入。 (Long)Math.sqrt(7660142319573120)的结果为87522239,但数学结果为87522238,999999994287166259537761...。 如果你乘以ans的值,为了存储为一个整数,这个值被舍入,你会得到比乘以精确结果更大的数字。

+0

如果是四舍五入,Math.sqrt(15)的答案应该是4,因为它是3.872983346207417 –

5

Math.sqrt操作上double S,不long S,SO mynum被转换到一个double第一。这是一个64位浮点数,它有“精度15-17位十进制数”(Wikipedia)。

您的输入号码有16位数字,所以您可能会失去输入精度。你也可能会失去输出的精度。

如果您确实需要long数字的整数平方根或通常数字太大而不能精确表示为double,请查看integer square root算法。

您也可以使用Guava图书馆的LongMath.sqrt()

4

您打电话给Math.sqrt很长。正如JavaDoc指出的那样,它返回一个“正确舍入的值”。

由于您的平方根不是非逗号值(87522238,999999994),因此您的结果会四舍五入到您的输出87522239

之后,数值的平方直观地大于mynum,因为您乘数大于根!

+0

如果是四舍五入,Math.sqrt(15)的答案应该是4,因为它是3.872983346207417 –

+0

@AbhilashMandaliya是的,没错,Math.sqrt()的结果是双精度的,但在你的例子中,它被转换为long:(long)Math.sqrt(mynum),所以它会自动舍入。尝试Math.sqrt(15)和(long)Math.sqrt(15)来看看区别 – RetteMich

+0

它只有在@IfOnly在下面提到时才有3 –

2
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); 

结果:

Double : 3.872983346207417 
Double : 15.000000000000002 
Long : 3 
Long : 9 

我希望这个说清楚。

干杯!

1

您不需要长型,所有数字都可以在double中表示,而Math.sqrt先转换为double,然后通过FPU指令(在标准PC上)计算平方根。

这种情况发生时对数字b=a^2-1其中a

67108865 <= a <= 94906265 

b平方根具有级数展开的范围内开始

a-1/(2*a)-1/(8*a^2)+... 

的整数。如果相对误差1/(2*a^2)下降到低于该机器epsilon,最接近double号码是a

在另一方面,对于这一招工作的人需要的是a*a-1.0double精确表示,这给条件

1/(2*a^2) <mu=2^(-53) < 1/(a^2) 

2^52 < a^2 < 2^53 
2^26+1=67108865 <= a <= floor(sqrt(2)*2^26)=94906265 
相关问题