您正面临精度和舍入的问题。
当你指数地减少一个数字时,它会收敛到零。如果它是一个有限精度的浮点数,将会有一个很小的数字,以任何可能的表示都无法与零区分。所以,像
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