[英]What is wrong with this while-loop (C++)?
我很確定自己做對了,但是顯然我沒有。 此while循環一旦達到0,便會無限運行。它會不斷重復輸出“每月付款:$ 0.00”和“該付款后的您的貸款:$ 0.00”。 我究竟做錯了什么?
while (loan_balance ! = 0)
{
monthly_payment = loan_balance / 20;
loan_balance = loan_balance - monthly_payment;
cout << "Monthly Payment: $" << monthly_payment << ends;
cout << "Your loan balance after that payment is: $" << loan_balance << endl;
}
如果load_balance
是浮點類型( float
或double
),則除非將其明確設置為load_balance = 0.0f
,否則load_balance != 0
(其中0
為0.0f
)可能永遠不會為假。 因此,應將其與一個較小的閾值進行比較,例如
while(load_balance >= 1e-4)
同樣,不等於的運算符是!=
,帶有空格! =
! =
是無效的。
貸款余額可能是浮動或兩倍; 它可能會減少到接近但不為0的程度。將您的比較值更改為“> 0”。
0是int
類型的數據類型
0.0f是double
或float
類型的數據類型
所以你是說
while(loan_balance != 0)
do stuff
作為回報,編譯器說:“如果loan_balance
永遠不會為0 ,所以我會繼續做。”
請記住:整數不是浮點數/雙精度數
您的loan_balance很有可能永遠不會真正精確地變為0。 我很確定您希望您的loan_balance浮動或加倍。
double loan_balance=23000.00;
while (loan_balance >0.000)
{
monthly_payment = loan_balance / 20.0;
loan_balance = loan_balance - monthly_payment;
cout << "Monthly Payment: $" << monthly_payment << ends;
cout << "Your loan balance after that payment is: $" << loan_balance << endl;
}
您面臨着精度和舍入的問題。
當您以指數形式減少一個數字時,它將收斂為零。 如果它是有限精度的浮點數,那么將有一個數字太小而無法用任何可能的表示形式與零區分開。 所以,像
double d=1.0; // or some other finite value
while(d!=0.0)
d*=ratio; // ratio is some finite value so that fabs(ratio)<1.0
將在有限數量的迭代中完成。
但是,根據d
和ratio
的值,尤其是當d
在次正規范圍內接近零(意味着較少的有效位)並且fabs(ratio)
接近1.0(緩慢收斂)時,選擇的舍入模式會導致d*ratio
為向d
舍入。 發生這種情況時,以上循環將永遠不會結束。
在支持IEC 60559的機器/編譯器中,您應該能夠使用fegetround()
和fesetround()
(在<fenv.h>
聲明fegetround()
來測試和設置浮點舍入模式。 您系統上的默認舍入很可能是最近的。 為了使上面的循環收斂更快(或完全收斂),最好使舍入趨向於0。
但是請注意,它帶有價格:根據應用程序的不同,由於精度/准確性的原因,更改舍入模式可能不是所希望的(OTOH,如果您已經處於次標准范圍內,那么精度可能就不再那么好了) 。
但是原始問題的收斂性問題仍然有些復雜,因為它是通過兩步操作完成的。 因此,除法運算中將進行一次舍入,而減法運算中將進行另一次舍入。 為了增加機會和收斂的速度,減法應該采取盡可能多的loan_balance
的價值越好,這樣也許圍捕會在這種情況下更好。 實際上,當我將fesetround(FP_UPWARD)
添加到OP的原始代碼中(連同將loan_balance
的初始值定義為1.0
)時,它在14466次迭代后收斂。 ( 但是請注意,這只是一個猜測 ,對原始代碼的影響可能只是一個特殊條件。有必要進行更深入的分析來限定它,並且這種分析必須考慮到不同的值比率,以及被減數和次要減價的相對優勢。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.