亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用 Newton-Raphson 方法計算平方根時的循環條件

使用 Newton-Raphson 方法計算平方根時的循環條件

藍山帝景 2022-11-02 17:22:48
我目前正在學習一門課程,講師使用以下代碼在 Java 中實現平方根功能 -public class Sqrt {     public static void main(String[] args) {         // read in the command-line argument        double c = Double.parseDouble(args[0]);        double epsilon = 1.0e-15;  // relative error tolerance        double t = c;              // estimate of the square root of c        // repeatedly apply Newton update step until desired precision is achieved        while (Math.abs(t - c/t) > epsilon*t) {            t = (c/t + t) / 2.0;        }        // print out the estimate of the square root of c        System.out.println(t);    }}但是,如果我將 while 循環條件稍微更改為而while (Math.abs(t - (c / t)) >= epsilon)不是while (Math.abs(t - (c / t)) >= t * epsilon),則對于某些輸入(如 234.0.0),程序會陷入無限循環。我使用了 Eclipse 調試器,發現我的代碼在某個點之后返回的 t 值接近 234 的平方根,但仍然大于 EPSILON。并且使用更新公式,每次迭代后都會產生相同的 t 值,因此循環會永遠卡在那里。有人可以解釋為什么程序在使用時失敗>= EPSILON但在使用時工作得很>= t * EPSILON好嗎?據我了解,鑒于 EPSILON 的值極小,t * EPSILON 最終不應與 EPSILON 相差太大,但在程序中實現時差異很大。
查看完整描述

2 回答

?
Helenr

TA貢獻1780條經驗 獲得超4個贊

您實際上可以使用調試器來查看數字的進展情況以及為什么例如 234 的平方根在epsilon不乘以時會導致無休止的循環t

我已經使用帶有日志斷點的 IntelliJ 來查看數字如何進行以及為什么會發生無休止的循環:

http://img1.sycdn.imooc.com//636237920001f02810800712.jpg

首先,我在日志斷點中使用了這個表達式:


" " + Math.abs(t - c/t) + " " + epsilon

對于此代碼:


private static void calcRoot(String arg) {

    // read in the command-line argument

    double c = Double.parseDouble(arg);

    double epsilon = 1.0e-15;  // relative error tolerance

    double t = c;              // estimate of the square root of c


    // repeatedly apply Newton update step until desired precision is achieved

    while (Math.abs(t - c/t) > epsilon ) {

        t = (c/t + t) / 2.0;

    }


    // print out the estimate of the square root of c

    System.out.println(t);

}

這是證明實際上epsilon小于的結果,Math.abs(t - c/t)并且Math.abs(t - c/t)在其進程中停止:


 233.0 1.0E-15

 115.50851063829788 1.0E-15

 55.82914775415816 1.0E-15

 24.47988606961853 1.0E-15

 7.647106514310517 1.0E-15

 0.927185521197492 1.0E-15

 0.014043197832668497 1.0E-15

 3.2230278765865705E-6 1.0E-15

 1.723066134218243E-13 1.0E-15

 1.7763568394002505E-15 1.0E-15

 1.7763568394002505E-15 1.0E-15

 1.7763568394002505E-15 1.0E-15

 1.7763568394002505E-15 1.0E-15

 1.7763568394002505E-15 1.0E-15

 1.7763568394002505E-15 1.0E-15

 1.7763568394002505E-15 1.0E-15

 ...

如果我然后使用epsilon * tI 并將日志記錄表達式更新為" " + Math.abs(t - c/t) + " " + epsilon * t我可以看到完全不同的控制臺輸出:


 233.0 2.34E-13

 115.50851063829788 1.175E-13

 55.82914775415816 5.974574468085106E-14

 24.47988606961853 3.1831170803771985E-14

 7.647106514310517 1.959122776896272E-14

 0.927185521197492 1.5767674511807463E-14

 0.014043197832668497 1.5304081751208715E-14

 3.2230278765865705E-6 1.529706015229238E-14

 1.723066134218243E-13 1.5297058540778443E-14

更新


如果你在BigDecimal課堂上嘗試同樣的事情,你將能夠計算 的平方根,234以防你選擇足夠的四舍五入數字(見scale下面的變量):


private static void calcRootBig(String arg) {

    // read in the command-line argument

    BigDecimal c = new BigDecimal(arg);

    BigDecimal epsilon = new BigDecimal(1.0e-15);  // relative error tolerance

    BigDecimal t = new BigDecimal(c.toString());              // estimate of the square root of c

    BigDecimal two = new BigDecimal("2.0");


    // repeatedly apply Newton update step until desired precision is achieved

    int scale = 10;

    while (t.subtract(c.divide(t, scale, RoundingMode.CEILING)).abs().compareTo(epsilon) > 0) {

        t = c.divide(t, scale, RoundingMode.CEILING).add(t).divide(two, scale, RoundingMode.CEILING);

    }


    // print out the estimate of the square root of c

    System.out.println(t);

}

但是,如果您只選擇 3 作為舍入比例,您將再次陷入無休止的循環。


因此,在您的情況下,實際上是浮點除法的精度導致了無休止的循環。的乘法epsilon * t只是克服默認浮點運算中舍入精度不足的一個技巧。


查看完整回答
反對 回復 2022-11-02
?
拉風的咖菲貓

TA貢獻1995條經驗 獲得超2個贊

double具有大約 15 位精度(或 1 到 2^52 或 4.5e15)。當您計算t * epsilon您需要 1 與1e15/234可能的比率的誤差double時,當您使用時,epsilon您需要 1 與 1 的比率,該比率處于1e15double 精度的極限,除非它是一個精確值并且錯誤是0. 例如,試試這個256,它可能會起作用,但任何不是精確值的東西都可能不起作用。

對任意端點的簡單解決方案是,一旦錯誤從一次迭代到下一次迭代沒有改善,就停止。這將為您提供使用此公式的最準確的解決方案。


查看完整回答
反對 回復 2022-11-02
  • 2 回答
  • 0 關注
  • 123 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號