获取近似平方根

我正在实施巴比伦方法来使用以下公式逼近n平方根:

nextGuess = (lastGuess + n / lastGuess) / 2;

所以当nextGuesslasGuess几乎相同时, nextGuess就是近似的平方根。

我们正在做的是检查nextGuesslastGuess是否小于0.0001等非常小的数字,然后我可以声称nextGuessn的近似平方根。 如果不是nextGuess变成lastGuess

那么我该如何以正确的方式实施呢?

我现在的代码:

public static void getApproximatedSquare(long n){
    DecimalFormat decimalFormat = new DecimalFormat("#.####");
    decimalFormat.setRoundingMode(RoundingMode.CEILING);

    double lastGuess = 1, nextGuess;

    nextGuess = (lastGuess + n / lastGuess) / 2;
    Double init =  0.0001;
    System.out.println(decimalFormat.format(init));
    if (Double.valueOf(decimalFormat.format(nextGuess)) <= init)
        //todo

}

目前的实施草案有一些缺陷:

  • 我怀疑你真的需要Double.valueOf(decimalFormat.format(...)) ,它只是从结果中删除一些精度
  • 你的收敛条件不是nextGuess < init但是difference_between_nextGuess_and_lastGuess < init
  • 你必须重复近似直到收敛,所以你不能只使用一个if 。 你需要一个forwhile或(在我的解决方案) do... while
  • 这应该工作(在每一步,它打印最后和下一个猜测)

    public static double getApproximatedSquare(long n) {
        DecimalFormat decimalFormat = new DecimalFormat("#.####");
        decimalFormat.setRoundingMode(RoundingMode.CEILING);
    
        double lastGuess, nextGuess = 1;
        double init = 0.0001;
        do {
            lastGuess = nextGuess;
            nextGuess = (lastGuess + (double) n / lastGuess) / 2;
            System.out.println(decimalFormat.format(lastGuess)+" ---> "+decimalFormat.format(nextGuess));
        } while (Math.abs(lastGuess - nextGuess) >= init);
        return nextGuess;
    }
    

  • 使用绝对容忍总是一个坏主意,因为它没有考虑到论证的大小顺序。 相对误差更好。

    但是在平方根的情况下,我建议一个更好的方法:确保初始近似值在确切根的√2范围内。 这是通过将参数的浮点表示中的2的指数减半来获得的。 (如果你不能访问这个指数,你可以通过连续的分割或乘法来获得它,直到达到间隔[1,2])。

    例如:对于27,您有16≤27 <32.然后1≤√27/ 4 <√2,您可以从4开始迭代。

    然后执行巴比伦公式的四次迭代 。 没有更少,没有更多。

    在这个例子中,经过四次迭代,你得到5.19615242271,这是确切的。


    如果你感觉连续减半或加倍过程很慢并且认为牛顿更快,考虑(x + n / x)/ 2> x / 2,这样牛顿实际上收敛得比半等分慢,并涉及更多算术!


    如果nextGuess的价值是100%肯定会下降并达到足够的价值,那么你不能这样做吗?

    public static void getApproximatedSquare(long n){
        DecimalFormat decimalFormat = new DecimalFormat("#.####");
        decimalFormat.setRoundingMode(RoundingMode.CEILING);
    
        double lastGuess = n + 1;
        double nextGuess = n;
        double init      = 0.0001;
    
        while (lastGuess - nextGuess > init)
        {
            lastGuess = nextGuess;
            nextGuess = (lastGuess + n / lastGuess) / 2;
        }
    
        System.out.println(decimalFormat.format(init));
    }
    
    链接地址: http://www.djcxy.com/p/86643.html

    上一篇: Get approximate square root

    下一篇: Square root in assembly, how to shift and change bits