long mynum = Long.parseLong("7660142319573120");
long ans = (long)Math.sqrt(mynum) // output = 87522239
long ans_ans = ans * ans;
在这种情况下,我得到了ans_ans> mynum应该在哪里< = mynum。为何如此行为?我也尝试使用节点js。结果也一样。
答案 0 :(得分:5)
Math.sqrt
在double
s上运行,而非long
s,因此mynum
首先转换为double
。这是一个64位浮点数,其精度为" 15-17十进制数" (Wikipedia)。
您的输入数字有16位数字,因此您可能已经失去输入的精确度。您可能也会在输出上失去精确度。
如果您确实需要long
个数字的整数平方根,或者通常数字太大而无法准确表示为double
,请查看integer square root算法。
您也可以使用Guava库中的LongMath.sqrt()
。
答案 1 :(得分:4)
你打电话给Math.sqrt
很长时间。
正如JavaDoc指出的那样,它返回一个正确舍入的值"。
由于您的平方根不是非逗号值(87522238,999999994
),因此您的结果会向上舍入为您的输出87522239
。
之后,值的平方直观地大于mynum
,因为你的数字乘以比根更大的数字!
答案 2 :(得分: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);
结果:
Double : 3.872983346207417
Double : 15.000000000000002
Long : 3
Long : 9
我希望这说清楚。
答案 3 :(得分:2)
答案是:四舍五入。
(Long)Math.sqrt(7660142319573120)
的结果为87522239
,但数学结果为87522238,999999994287166259537761...
。
如果将ans
值乘以向上舍入以便存储为整数,您将获得比乘以精确结果更大的数字。
答案 4 :(得分:1)
您不需要long类型,所有数字都可以在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.0
在double
中完全可以表示,这就是条件
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