这是一个Java代码,要求输入一个数字,然后不使用Math.sqrt()方法打印其平方根:
import java.util.Random;
import java.io.*;
public class Square {
public static void main(String[] args) throws IOException {
final double TOL = 0.5E-15;
InputStreamReader reader = new InputStreamReader(System.in);
BufferedReader input = new BufferedReader(reader);
System.out.print("Enter a number to get the aquare of it: ");
double n = new Double(input.readLine()).doubleValue();
Random random = new Random();
double x = random.nextDouble();
do {
x = (x+n/x)/2;
} while(Math.abs(x*x-n)>TOL*2*x);
System.out.println("sqrt(" + n + ") = " + x);
}
}
请在您的计算机上运行并测试几个数字。 对于低于30.1的数字,它运行并快速计算平方根。但是当你输入30.2或更大的数字时,不计算平方根(至少在可行的等待时间)! 这种行为有什么有趣的解释吗?!
答案 0 :(得分:4)
将do-while更改为:
do {
x = (x+n/x)/2;
System.out.println(x);
System.out.println(x*x);
} while(Math.abs(x*x-n)>TOL*2*x);
这重复(输入30.2):
5.495452665613634
30.199999999999992
正如您所看到的那样是5.495452665613634 30.199999999999992的平方,这导致条件Math.abs(x*x-n)>TOL*2*x
始终满满(差异为7.105427357601002E-15
。条件为> 5.4954526656136345E-15
,其中是真的)
换句话说,你忘记了计算机程序存储值有一些限制,或者你的TOL不够高
答案 1 :(得分:2)
整个代码的构建基于这样的前提:在某些时候,您将获得x的正确值。从Random对象获得的内容将影响时间以及您选择的数字大小。
这不是计算sqrt的有效方法。
答案 2 :(得分:0)
为什么随机?一个明智的编码双重选择避免像x*x
在您的代码中,您可以将*2
添加到TOL定义并从循环中删除*2
良好的编程删除所有不必要的东西
答案 3 :(得分:0)
“问题”是double
具有有限的精度:表示的数字越大,不准确度越大 - 存储不同double
的最小变化越大。< / p>
一旦您尝试的答案超过某个数字大小,double
无法很好地解析数字,以达到TOL
定义的准确度。
答案 4 :(得分:0)
你所拥有的是用于计算数字平方根的所谓Babylonian method。但是,我认为您的停止条件应该只是一个标量(例如TOL
)而不是TOL*2*x
。