1

这是一个 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 或更大的数字时,不会计算平方根(至少在可行的等待情况下)!这种行为有什么有趣的解释吗?!

4

5 回答 5

4

将执行时间更改为:

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 不够高

于 2013-07-31T15:27:24.510 回答
2

好吧,整个代码都是建立在这样的前提下的:在某些时候你会得到正确的 x 值。您从 Random 对象中获得的内容将影响时间,您选择的数字的大小也会影响时间。

这并不是计算 sqrt 的有效方法。

于 2013-07-31T15:30:40.957 回答
0

为什么随机?明智地选择编码的双重避免计算x*x


在您的代码中,您可以添加*2到 TOL 定义并*2从循环中删除

好的编程去掉所有不必要的东西

于 2013-07-31T15:37:00.553 回答
0

“问题”是double精度有限:表示的数字越大,不准确性就越大 - 也就是说,存储不同的最小变化必须越大double

一旦您尝试的答案超过了某个数字大小,double就无法将数字解析得足够精细以达到定义的准确度TOL

于 2013-07-31T15:38:23.567 回答
0

你所拥有的是所谓的巴比伦方法来计算一个数字的平方根。但是,我认为您的停止条件应该只是一个标量(例如TOL)而不是TOL*2*x

于 2013-07-31T15:47:32.343 回答