简体   繁体   中英

What is wrong with this while-loop (C++)?

I was pretty sure I was doing this the right way, but apparently I'm not. This while loops keeps running infinitely once it reaches 0. It keeps outputting "Monthly Payment: $0.00" and "Your loan after that payment is: $0.00" over and over again. What am I doing wrong?

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;
  }

If load_balance is a floating point type ( float or double ), then load_balance != 0 (where 0 is 0.0f ) will likely never be false unless it is explicitly set to load_balance = 0.0f . So it should be compared to a small threshold instead, eg

while(load_balance >= 1e-4)

Also the not-equal operator is != , with a space ! = ! = is doesn't work.

loan_balance is probably a float or double; it might decrease to be something close to but not quite 0. Change your comparison to "> 0".

0 is a data type of type int

0.0f is a data type of type double or float

So you're saying

while(loan_balance != 0)
  do stuff

The compiler in return says: " loan_balance will never ever be 0 if it is a double/float, so I'll just keep doing stuff."

Keep in mind: integers aren't floats/doubles

Your loan_balance is most likely never actually going to be 0 exactly. I am pretty sure you want your loan_balance in float or double.

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;
  }

You're facing a problem with both precision and rounding.

When you exponentially decrease a number, it will converge to zero. If it is a limited precision floating point number, there will be a number that is so small that cannot be distinguishable from zero with any possible representation. So, a loop like

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

would finish in a finite number of iterations.

However, depending on the values of d and ratio , especially when d approaches zero in the subnormal range (implying fewer significant bits) and fabs(ratio) is close to 1.0 (slow convergence), the selected rounding mode can cause d*ratio to be rounded towards d . When that happens, the loop above will never end.

In machines/compilers that support IEC 60559, you should be able to test and set the floating point rounding mode, using fegetround() and fesetround() (declared in <fenv.h> ). It is likely that the default rounding on your system is to the nearest. For the loop above to converge more quickly (or at all), it would be better to cause rounding to be toward 0.

Note however, that it comes with a price: depending on the application changing the rounding mode might be undesirable on the grounds of precision/accuracy (OTOH, if your already working in the subnormal range, your precision is probably not that good anymore anyway).

But the original question's convergence problem is still a little bit more complicated, because it is done with a two-step operation. So there is one rounding in the division operation, and another one in the subtraction. To increase the chance and speed of convergence, the subtraction should take as much of loan_balance 's value as possible, so maybe rounding up would be better in this case. In fact, when I added fesetround(FP_UPWARD) to the OP's original code (together with defining the initial value of loan_balance to 1.0 ), it converged after 14466 iterations. ( Note however that that is just a guess , and the effect on the original code might have been just a special condition. A more in-depth analysis would be necessary to qualify it, and such an analysis would have to take into account different values of ratio, and the relative greatness of minuend and subtrahend.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM