1

thanks in advance. I'm writing a C++ assignment for class where we're creating our own money/currency class. I'm having trouble figuring out why my passing of a float isn't giving me enough precision.

Implementation:

private:
    long int DOLLARS;
    short int CENTS;

Currency::Currency(float tmpMoney)
{
// cout << "tmpMoney is: " << tmpMoney << endl;
    int tmpDollar;
    float tmpCent;
    tmpDollar = static_cast<int>(tmpMoney);
    tmpCent = (tmpMoney-tmpDollar)*100;
    DOLLARS = tmpDollar;
    CENTS = tmpCent;
    }

Main Program:

Currency c1(2342.59);
Currency c2(2342.515); // there is no half cent coin, round it to 2342.52

If I output 'tmpMoney' it just gives me (for c2) 2345.51. I'm not sure how to round .515 if the value doesn't even go that far.

ThePeter
  • 33
  • 1
  • 7
  • 5
    If you can avoid it, don't use floating point for money. You typically want to use an integer number of the smallest unit you care about (apparently cents in this case). – Jerry Coffin Sep 17 '14 at 19:43

2 Answers2

3

It's a bad idea to make a currency type be constructible from floating-point type.

7 decimal digits is in general beyond float precision. You can still get desired output by:

float tmpMoney = 2342.515;
cout << setprecision(7) << tmpMoney << endl;
// 2342.515

But the internal representation is far from perfect:

cout << setprecision(10) << tmpMoney << endl;
// 2342.514893

If the number is large enough, you'll lose more:

float tmpMoney = 123456789.12;
cout << setprecision(12) << tmpMoney << endl;
// 123456792

So you may decide to use double instead, but you should be really careful because for large enough numbers you'll get the same errors:

double tmpMoney = 3333333333333333.42; // 17 digits 
cout << setprecision(18) << tmpMoney << endl;
// 3333333333333333.5

If there is a chance that you'll have such numbers, don't initialize Currency with double either.

I would advise you to have just a constructor like Currency(int dollars, int cents).

You can also check this question for some insights.

Community
  • 1
  • 1
Anton Savin
  • 40,838
  • 8
  • 54
  • 90
1
    #include <cmath>

    CENTS = round(tmpCent);

Due to floating point representation, this may not always give the right result. The closest you can get is have a margin of error epsilon, say

    #define EPS 0.000001

then you can do

    CENTS = round(tmpCent + EPS);

Note that this will accept values that are represented as 0.499999 <= x < 0.5

And it's preferable to use double and not float to keep the precision as close as possible.

Olayinka
  • 2,813
  • 2
  • 25
  • 43
  • That doesn't work. tmpMoney's value at the start of the constructor is "2342.51" so it doesn't include a third number after the decimal point. – ThePeter Sep 17 '14 at 19:47
  • 1
    @DancinPeter use double not float. – Olayinka Sep 17 '14 at 19:48
  • I've written my entire thing based on float. I tried changing it, but I'm getting TONS of ambiguity issues. – ThePeter Sep 17 '14 at 19:52
  • 1
    @DancinPeter the problem is floating point precision. change the 5 to 6 and it will work just right. The number isn't represented as you see it. – Olayinka Sep 17 '14 at 19:55
  • I'm not the one testing the program. My teacher is. So if he decides he wants to test .515 then I'm screwed. – ThePeter Sep 17 '14 at 19:58