为什么Math.sqrt()在java中输出错误的值?

时间:2017-02-16 07:52:38

标签: java math

long mynum = Long.parseLong("7660142319573120");
long ans = (long)Math.sqrt(mynum) // output = 87522239
long ans_ans = ans * ans;

在这种情况下,我得到了ans_ans> mynum应该在哪里< = mynum。为何如此行为?我也尝试使用节点js。结果也一样。

5 个答案:

答案 0 :(得分:5)

Math.sqrtdouble 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.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