您正面臨精度和舍入的問題。
當你指數地減少一個數字時,它會收斂到零。如果它是一個有限精度的浮點數,將會有一個很小的數字,以任何可能的表示都無法與零區分。所以,像
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>
中聲明)測試和設置浮點舍入模式。系統上的默認舍入很可能是最接近的。對於上面的循環更快地收斂(或根本),最好是使得舍入趨向於0.
但是請注意,它帶有一個價格:根據應用程序的不同,舍入模式可能會不同基於精度/準確性(OTOH,如果您已經在低於正常範圍內工作,您的精度可能不再那麼好),這是不理想的。
但原來的問題的銜接問題仍然比較複雜一點,因爲它是一個兩步操作完成。所以在除法操作中有一個四捨五入的結果,另一個在減法中。爲了增加收斂的機會和速度,減法應該儘可能多地取儘可能多的值,所以在這種情況下,或四捨五入會更好。實際上,當我在OP的原始代碼中加上fesetround(FP_UPWARD)
(連同定義loan_balance
的初始值到1.0
),它在14466次迭代之後收斂。 (然而要注意,這只是一個猜測,並在原代碼的影響可能是隻是一個特殊的條件。更深入的分析,有必要限定它,而這樣的分析必須考慮到比的不同的值,和被減數和減數的相對偉大。)
你與調試器步?是'monthly_payment'曾經'0',如果是這樣你不會改變'loan_balance' – CoryKramer
什麼變量類型是'loan_balance'和'monthly_payment'? –
@NoamHacker他們都是雙打類型。 – Bluasul