创建一个程序,在不使用Math.sqrt的情况下计算数字的平方根

时间:2016-01-26 11:39:33

标签: java

这是可用于计算数字平方根的公式。

result=(guess+(number/guess))/2;

例如,我需要得到9的平方根。首先,我需要猜测。对于这个,它是6.虽然,我知道9的平方根是3,但我选择了6以显示该程序应该如何工作。

这使......

result=(6+(9/6))/2 which is equal to 3.75. 

要获得9的实际平方根,我需要将结果作为新的猜测。程序应该继续作为......

result=(3.75+(9/3.75))/2 which is equal to 3.075.

此过程应该继续,直到结果与结果之后的差值等于0.例如

result=(3+(9/3))/2 is always equal to 3. 

当结果的值传递给guess时,下一个结果也将是3.这意味着3是9的平方根。

这是我的代码:

package javaPackage;

public class SquareRoot {

    public static void main(String[] args) {
        calcRoot();
    }

    public static void calcRoot(){
        double num=9;
        double guess=6;
        double result=0;

        while(Math.abs(guess-ans)!=0){
            result=(guess+(num/guess))/2;       
            guess=result;
        }
    System.out.print(result);
    }
}

输出

3.75

我的问题是我无法比较结果的值和之前的结果。由于猜测等于结果,因此猜测和结果之后的程序已经相等。我该如何解决?

5 个答案:

答案 0 :(得分:3)

只需在while循环中交换两个语句(以及初始化以避免除以零):

public static void calcRoot(){
    double num=9;
    double guess=0;
    double result=6;

    while(Math.abs(guess-result)!=0){
        guess=result;
        result=(guess+(num/guess))/2;       
    }
System.out.print(result);
}

诀窍是在执行测试时将旧值保留在guess中,将新值保留在result中。

你不应该测试!= 0,由于舍入错误,这可能无法实现。更好地测试一些小值>= 1e-7

答案 1 :(得分:0)

要将结果与之前的结果进行比较,您需要将它们保存在变量中。

这是一个二进制印章。

public static double sqrt(double ans) {
    if (ans < 1)
        return 1.0 / sqrt(1.0 / ans);
    double guess = 1;
    double add = ans / 2;
    while (add >= Math.ulp(guess)) {
        double guess2 = guess + add;
        double result = guess2 * guess2;
        if (result < ans)
            guess = guess2;
        else if (result == ans)
            return guess2;
        add /= 2;
    }
    return guess;
}

public static void main(String[] args) {
    for (int i = 0; i <= 10; i++)
        System.out.println(sqrt(i) + " vs " + Math.sqrt(i));
}

打印

0.0 vs 0.0
1.0 vs 1.0
1.414213562373095 vs 1.4142135623730951
1.7320508075688772 vs 1.7320508075688772
2.0 vs 2.0
2.236067977499789 vs 2.23606797749979
2.449489742783178 vs 2.449489742783178
2.64575131106459 vs 2.6457513110645907
2.82842712474619 vs 2.8284271247461903
3.0 vs 3.0
3.162277660168379 vs 3.1622776601683795

    for (int i = 0; i <= 10; i++)
        System.out.println(i / 10.0 + ": " + sqrt(i / 10.0) + " vs " + Math.sqrt(i / 10.0));

打印

0.0: 0.0 vs 0.0
0.1: 0.31622776601683794 vs 0.31622776601683794
0.2: 0.4472135954999581 vs 0.4472135954999579
0.3: 0.5477225575051662 vs 0.5477225575051661
0.4: 0.6324555320336759 vs 0.6324555320336759
0.5: 0.7071067811865476 vs 0.7071067811865476
0.6: 0.7745966692414834 vs 0.7745966692414834
0.7: 0.8366600265340758 vs 0.8366600265340756
0.8: 0.894427190999916 vs 0.8944271909999159
0.9: 0.9486832980505138 vs 0.9486832980505138
1.0: 1.0 vs 1.0

答案 2 :(得分:0)

public static double sqrt(double number)
{
    double dd=number, sqi, sqrt=0;
    long i, b=0, e=0, c=1, z, d=(long)number, r=0, j;
    for (i=1l, sqi=1; ; i*=100l, sqi*=10)
    {
        if (i>dd)
        {
            i/=100;
            sqi/=10;
            j=i;
            break;
        }
    }
    for (z=0l; z<16; dd=(dd-(double)(r*i))*100, j/=100l, sqi/=10, z++)
    {
        r=(long)(dd/i);
        d=(e*100l)+r;
        int a=9;
        for (c=((b*10l)+a)*a; ; a--)
        {
            c=((b*10l)+a)*a;
            if (c<=d)
                break;
        }
        //if (a>=0)
        //    System.out.print(a);
        e=d-c;
        sqrt+=a*sqi;
        if (number==sqrt*sqrt && j==1)
            break;
        //if (j==1)
        //    System.out.print('.');
        b=b*10l+2l*(a);
    }
    return sqrt;
}

抱歉未定义的变量名....但这个程序确实有效! 该程序基于查找平方根的长除法

答案 3 :(得分:0)

只需创建另一个变量来存储上一个猜测的值。 这是代码:

package javaPackage;

public class SquareRoot {

    public static void main(String[] args) {
        calcRoot();
    }

    public static void calcRoot(){
        double num=9;
        double guess=6;
        double prevGuess=0;
        double result=0;

        while(Math.abs(guess-prevGuess)!=0){
            result=(guess+(num/guess))/2;
            prevGuess = guess;
            guess=result;
        }
        System.out.print(result);
    }
}

答案 4 :(得分:0)

为了提高性能,请遵循以下代码:

    public static double sqrt(double num) {
    double half = 0.5 * num;
    long bit = Double.doubleToLongBits(num);
    bit = 0x5fe6ec85e7de30daL - (bit >> 1);
    num = Double.longBitsToDouble(bit);

    for (int index = 0; index < 4; index++) {
        num = num * (1.5f - half * num * num);
    }

    return 1 / num;
}

关于magic号码0x5fe6ec85e7de30daL,您可以看到FAST INVERSE SQUARE ROOT 让我们看看性能,测试代码:

    double test = 123456;

    //trigger the jit compiler
    for (int index = 0; index < 100000000; index++) {
        sqrt(test);
    }
    for (int index = 0; index < 100000000; index++) {
        Math.sqrt(test);
    }


    //performance
    long start = System.currentTimeMillis();
    for (long index = 0; index < 10000000000L; index++) {
        sqrt(test);
    }
    System.out.println("this:"+(System.currentTimeMillis() - start));
    start = System.currentTimeMillis();
    for (long index = 0; index < 10000000000L; index++) {
        Math.sqrt(test);
    }
    System.out.println("system:"+(System.currentTimeMillis() - start));


    System.out.println(sqrt(test));
    System.out.println(Math.sqrt(test));

结果是:

this:3327
system:3236
this result:351.363060095964
system result:351.363060095964