CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 12 of 12
  1. #1
    Join Date
    Oct 2010
    Posts
    1

    double to int issue. losing a penny

    For class I have to write a program that will take in the conversion rate from euros to dollars and the amount of euros the person has. Then it is supposed to convert to US dollars and then distribute the money into dollars, quarters, dimes, nickels, and pennies.

    So far I can get everything to work but I lose a penny.

    For example I enter in the conversion rate of .7266 (rate as of last night) and put in that I have 5000 euros.

    I get 6881.37 US dollars.

    with 6881 dollars, 1 quarter, 1 dime, 0 nickes, 1 penny. This adds up to 6811.36.

    I am not really sure why this is happening.

    Here is the code

    ==============

    #include <iostream>
    using namespace std;

    int main() {

    cout << "Hello, travelers! \n\n" << "Enter the conversion rate from euros to dollars (i.e. how many euros in a US dollar):";

    double numEurosPerDollar = 0;
    cin >> numEurosPerDollar;

    cout << "\n\nThe conversion rate you entered means that one US dollar is equivalent to " << numEurosPerDollar << " euros today. \n\n";

    cout << "Now enter the total amount you'd like to convert from euros to USD (up to hundreths of a euro):";

    double numEuros = 0;
    cin >> numEuros;

    double numDollars = numEuros / numEurosPerDollar;

    cout << "\n\n" << numEuros << " euros will convert to " << numDollars << " US dollars.\n\n";

    cout << "If you were to make this from change, using the biggest denomination at every step, it would be:\n\n";

    const int PENNIES_PER_DOLLAR = 100;
    const int PENNIES_PER_NICKEL = 5;
    const int PENNIES_PER_DIME = 10;
    const int PENNIES_PER_QUARTER = 25;

    int numPennies = numDollars * PENNIES_PER_DOLLAR;
    int numPenniesLeftOver = numPennies % PENNIES_PER_DOLLAR;
    //this gives us whole dollars and left over pennies.

    int numQuarters = numPenniesLeftOver / PENNIES_PER_QUARTER;
    numPenniesLeftOver = numPenniesLeftOver % PENNIES_PER_QUARTER;
    //this gives us whole quarters and left over pennies.

    int numDimes = numPenniesLeftOver / PENNIES_PER_DIME ;
    numPenniesLeftOver = numPenniesLeftOver % PENNIES_PER_DIME;
    //this gives us whole dimes and left over pennies.

    int numNickel = numPenniesLeftOver / PENNIES_PER_NICKEL;
    numPenniesLeftOver = numPenniesLeftOver % PENNIES_PER_NICKEL;
    //this gives uf whole nickels and left over pennies.

    cout << (int)numDollars << " dollars, " << numQuarters << " quarters, " << numDimes << " dimes, " << numNickel << " nickels, and " << numPenniesLeftOver << " pennies.";

    cout << "\n\n";
    return 0;

    }
    ============

  2. #2
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,675

    Re: double to int issue. losing a penny

    Quote Originally Posted by Voski View Post
    So far I can get everything to work but I lose a penny.

    For example I enter in the conversion rate of .7266 (rate as of last night) and put in that I have 5000 euros.

    I get 6881.37 US dollars.

    with 6881 dollars, 1 quarter, 1 dime, 0 nickes, 1 penny. This adds up to 6811.36.
    The output you get from the double variable is rounded to the nearest value with two decimals. Actually it's 6881.3652628681530415634461877236 $ (according to the Windows Calculator). But the conversion from double to int truncates the value downwards to the next integral value. That's where your cent gets lost.

    BTW, please use code tags when posting code next time. This will make it much more readable.

    Ah, and... Welcome to CodeGuru!
    I was thrown out of college for cheating on the metaphysics exam; I looked into the soul of the boy sitting next to me.

    This is a snakeskin jacket! And for me it's a symbol of my individuality, and my belief... in personal freedom.

  3. #3
    Join Date
    Aug 2005
    Location
    San Diego, CA
    Posts
    1,054

    Lightbulb Re: double to int issue. losing a penny

    Use code tags and properly indent within the tags.
    http://www.codeguru.com/forum/misc.php?do=bbcode#code

    The calculation of change seems correct to me but the output stream is a rounded number to two decimal points. Sorry I don't know what the default precision is supposed to be or how you can stop it from rounding. Clearly there is no such thing as 0.5 pennies so in that kind of conversion anything less then whole pennies would have to be truncated. This is why your change calculation is correct but the output of dollars.cents is showing .37. You may have to manually truncate the variable prior to output because I cannot seem to find an io manipulator that will stop the rounding from occurring.

  4. #4
    Join Date
    Aug 2005
    Location
    San Diego, CA
    Posts
    1,054

    Re: double to int issue. losing a penny

    Take a look at this.
    http://www.parashift.com/c++-faq-lit...html#faq-29.16

    It seems annoying that the iomanip doesn't include anything to truncate but I think that it is impossible to implement due to problems across platforms with floating point representations. If I manually truncate in the following way I still get a strange response, consistent with that explanation. This code will give you what you want (xxxx.36) but if you step with the debugger you'll see that numDollars is now xxxx.35999999997 or something to that effect. It simply isn't possible to truncate the way you think you should be able to because in the computer it is not possible to represent 0.36 perfectly.

    double numDollars = numEuros / numEurosPerDollar;
    numDollars = floor(numDollars*100.0) / 100.0;
    cout << "\n\n" << numEuros << " euros will convert to " << numDollars << " US dollars.\n\n";

    // prints 0.36 as I expect but in the debugger value is 0.35999999999999999
    double value(.36);
    std::cout << "value : " << value << std::endl;

  5. #5
    Join Date
    Apr 2005
    Posts
    107

    Re: double to int issue. losing a penny

    Honestly, you shouldn't use ANY approximate data type (floating point) when dealing with money. Double's are still floating point numbers.

    For any financial calculation, you should use a fixed point (even implied) numeric format.

    Rather then summarize information, see here: http://docs.sun.com/source/806-3568/ncg_goldberg.html

  6. #6
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: double to int issue. losing a penny

    Quote Originally Posted by kempofighter View Post
    It seems annoying that the iomanip doesn't include anything to truncate but I think that it is impossible to implement due to problems across platforms with floating point representations. If I manually truncate in the following way I still get a strange response, consistent with that explanation. This code will give you what you want (xxxx.36) but if you step with the debugger you'll see that numDollars is now xxxx.35999999997 or something to that effect. It simply isn't possible to truncate the way you think you should be able to because in the computer it is not possible to represent 0.36 perfectly.
    While the admonition against using floating point types for money stands, you can indeed specify a set number of fractional digits using iomanip. Note that the behavior of setprecision changes in the fixed and scientific modes:

    Code:
    double val = 12345.359999999;
    cout << std::fixed << std::setprecision(2) << val;

  7. #7
    Join Date
    Aug 2005
    Location
    San Diego, CA
    Posts
    1,054

    Lightbulb Re: double to int issue. losing a penny

    Quote Originally Posted by Lindley View Post
    While the admonition against using floating point types for money stands, you can indeed specify a set number of fractional digits using iomanip. Note that the behavior of setprecision changes in the fixed and scientific modes:

    Code:
    double val = 12345.359999999;
    cout << std::fixed << std::setprecision(2) << val;
    I'm well aware of that but those methods round. They do not help in any way whatsoever unless you manually perform the truncation yourself. In the OPs example he ends up with something like 12345.365. Using your method he would still end up with .37 which is not correct.

    I do have some experience with fixed point math and it is not entirely precise either. You tend to lose some precision depending on how many bits you are using to represent each side of the decimal point. I'm not convinced that it is any better for these operations then floating point.

  8. #8
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: double to int issue. losing a penny

    Quote Originally Posted by kempofighter View Post
    I do have some experience with fixed point math and it is not entirely precise either. You tend to lose some precision depending on how many bits you are using to represent each side of the decimal point. I'm not convinced that it is any better for these operations then floating point.
    Yes, but the errors are a lot more predictable with fixed-point, and generally will not accumulate unless you multiply excessively (to the point where you run out of bits) or you divide. Since neither of those is a common operation in finance, it generally isn't a problem. (Multiplying by an interest rate is fine, since it's unit-less the number of fractional bits doesn't change. You may compute a fractional cent which you can't store, but there are standard ways of dealing with that.)

  9. #9
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: double to int issue. losing a penny

    Quote Originally Posted by kempofighter View Post
    I do have some experience with fixed point math and it is not entirely precise either. You tend to lose some precision depending on how many bits you are using to represent each side of the decimal point. I'm not convinced that it is any better for these operations then floating point.
    No you don't. fixed point arithmetic is always 100% exact, 100% of the time. I grant you have a reduced range of values, and you can overflow, but that is a very different problem (and quasi nonexistent with the correct integer width).
    Is your question related to IO?
    Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
    It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.

  10. #10
    Join Date
    Oct 2008
    Posts
    1,456

    Re: double to int issue. losing a penny

    Quote Originally Posted by monarch_dodra View Post
    fixed point arithmetic is always 100% exact, 100% of the time. I grant you have a reduced range of values, and you can overflow...
    in principle, the same claim applies for floating point numbers, in the sense that you could in principle predict the exact amount of error induced by an operation with floating numbers ( although, as Lindley said, it's a much more difficult task ). The problem is that the IEEE standard for floating point numbers specifically admits "non strict" evaluation of floating point expressions, so, in practice, the actual error is essentially unpredictable ...

  11. #11
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: double to int issue. losing a penny

    Quote Originally Posted by superbonzo View Post
    in principle, the same claim applies for floating point numbers, in the sense that you could in principle predict the exact amount of error induced by an operation with floating numbers ( although, as Lindley said, it's a much more difficult task ). The problem is that the IEEE standard for floating point numbers specifically admits "non strict" evaluation of floating point expressions, so, in practice, the actual error is essentially unpredictable ...
    Can you? It was my understanding that the exact error was not only very difficult to work with, but literally non-deterministic.

    here, http://www.parashift.com/c++-faq-lit...html#faq-29.18

    That said, I'm not sure what you mean by "non strict".
    Is your question related to IO?
    Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
    It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.

  12. #12
    Join Date
    Oct 2008
    Posts
    1,456

    Re: double to int issue. losing a penny

    Quote Originally Posted by monarch_dodra View Post
    It was my understanding that the exact error was not only very difficult to work with, but literally non-deterministic.
    yes, I said "in principle" meaning "in theory" ... hence, I concluded saying that the error is "essentially unpredictable".

    Quote Originally Posted by monarch_dodra View Post
    That said, I'm not sure what you mean by "non strict".
    basically, the behavior described in the link in your post; moreover, compilers are free to "arithmetically" interpret floating point expressions as they like ( for example, x/y could be x*1./y and so on ... )
    Last edited by superbonzo; October 6th, 2010 at 05:12 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured