Question

Floating point division is causing a value that should be 1 to be .9999999 thus flooring it becomes 0 instead of 1 so the calculation for the required change is incorrect. What's the simplest way to deal with this? (Also if there's some sort of guide/article for how to deal with this I'd love a link for reference.) Ex. 3.51 is broken.

Both versions of the code have the same issue.

#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
//3.51 is broken due to floating point issue of .999999999 instead of 1. Work around?
int main(int argc, char *argv[]) 
{   
    const float DOLLARVALUE=1.0;
    const float QUARTERVALUE=0.25;
    const float DIMEVALUE=0.10;
    const float NICKELVALUE=0.05;
    const float PENNIEVALUE=0.01;
    const int CELLWIDTH=12;
    float totalChange=0;
    int countDollars=0;
    int countQuarters=0;
    int countDimes=0;
    int countNickels=0;
    int countPennies=0;
    float remainingTotal=0;


    cout<<"Please insert total amount of change needed: ";
    cin>>totalChange;
    cout<<endl;

    remainingTotal=totalChange;


    countDollars=(remainingTotal/DOLLARVALUE);
    remainingTotal=(remainingTotal-(countDollars*DOLLARVALUE));

    countQuarters=(remainingTotal/QUARTERVALUE);
    remainingTotal=(remainingTotal-(countQuarters*QUARTERVALUE));

    countDimes=(remainingTotal/DIMEVALUE);
    remainingTotal=(remainingTotal-(countDimes*DIMEVALUE));

    countNickels=(remainingTotal/NICKELVALUE);
    remainingTotal=(remainingTotal-(countNickels*NICKELVALUE));

    countPennies=(remainingTotal/PENNIEVALUE);
    remainingTotal=(remainingTotal-(countPennies*PENNIEVALUE));
    //cout<<fixed<<setprecision(0);
    cout<<"This amount can be given in change by:";
    cout<<endl;
    cout<<endl;

    cout<<"Dollars"<<setw(CELLWIDTH)<<"Quarters";
    cout<<setw(CELLWIDTH)<<"Dimes"<<setw(CELLWIDTH)<<"Nickles";
    cout<<setw(CELLWIDTH)<<"Pennies";
    cout<<endl;
    cout<<"------------------------------------------------------";
    cout<<endl;

    cout<<setw(4)<<countDollars;
    cout<<setw(CELLWIDTH)<<countQuarters;
    cout<<setw(CELLWIDTH)<<countDimes;
    cout<<setw(CELLWIDTH)<<countNickels;
    cout<<setw(CELLWIDTH)<<countPennies;

    cout<<endl;
    cout<<endl;

    return 0;
}

The next version has the same issues in a more explicit way.

#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
//3.51 is broken due to floating point issue of .999999999 instead of 1. Work around?
int main(int argc, char *argv[]) 
{   
    const float DOLLARVALUE=1.0;
    const float QUARTERVALUE=0.25;
    const float DIMEVALUE=0.10;
    const float NICKELVALUE=0.05;
    const float PENNIEVALUE=0.01;
    const int CELLWIDTH=12;
    float totalChange=0;
    float countDollars=0;
    float countQuarters=0;
    float countDimes=0;
    float countNickels=0;
    float countPennies=0;
    float remainingTotal=0;


    cout<<"Please insert total amount of change needed: ";
    cin>>totalChange;
    cout<<endl;

    remainingTotal=totalChange;


    countDollars=floor(remainingTotal/DOLLARVALUE);
    remainingTotal=(remainingTotal-(countDollars*DOLLARVALUE));


    countQuarters=floor(remainingTotal/QUARTERVALUE);
    remainingTotal=(remainingTotal-(countQuarters*QUARTERVALUE));

    countDimes=floor(remainingTotal/DIMEVALUE);
    remainingTotal=(remainingTotal-(countDimes*DIMEVALUE));

    countNickels=floor(remainingTotal/NICKELVALUE);
    remainingTotal=(remainingTotal-(countNickels*NICKELVALUE));

    countPennies=floor(remainingTotal/PENNIEVALUE);
    remainingTotal=(remainingTotal-(countPennies*PENNIEVALUE));

    cout<<"Amount of change needed is: "<<totalChange;
    cout<<endl;
    cout<<endl;
    //cout<<fixed<<setprecision(0);
    cout<<"This amount can be given in change by:";
    cout<<endl;
    cout<<endl;

    cout<<"Dollars"<<setw(CELLWIDTH)<<"Quarters";
    cout<<setw(CELLWIDTH)<<"Dimes"<<setw(CELLWIDTH)<<"Nickles";
    cout<<setw(CELLWIDTH)<<"Pennies";
    cout<<endl;
    cout<<"------------------------------------------------------";
    cout<<endl;



    cout<<setw(4)<<countDollars;
    cout<<setw(CELLWIDTH)<<countQuarters;
    cout<<setw(CELLWIDTH)<<countDimes;
    cout<<setw(CELLWIDTH)<<countNickels;
    cout<<setw(CELLWIDTH)<<countPennies;

    cout<<endl;
    cout<<endl;

    return 0;
}

Is there a simple workaround for this? I'm open to all ideas.

Was it helpful?

Solution

There are several ways you could easily fix this:

  1. Use integers or rational numbers instead of floating point numbers.

  2. Use rounding instead of truncating where applicable. You can implement round(x) simply as floor(x + 0.5). Not particularly suitable in your case, but it leads straightforwardly to the next one.

  3. You can round at higher decimals and then floor. Say you want to floor anything lower than 0.9999 to 0, but 0.9999 or anything higher should be floored to 1. Then all you need is to use floor(x + 0.0001) instead of floor(x).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top