CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 2 of 2 FirstFirst 12
Results 16 to 23 of 23
  1. #16
    Join Date
    Feb 2009
    Location
    Portland, OR
    Posts
    1,488

    Re: Adding doubles together produces different results in Release vs. Debug mode.

    Quote Originally Posted by VladimirF View Post
    What was the point of this code? Ans how it differs from:
    Code:
    _tprintf(_T("%.2f"), fAmt);
    The multiply and then divide by 1000 part ensures that he doesn't lose the 3-rd decimal place, i.e. 1237.8599999999999 becomes 1237.86 and 1237.8549999999999 becomes 1237.85.

  2. #17
    Join Date
    Feb 2009
    Location
    Portland, OR
    Posts
    1,488

    Re: Adding doubles together produces different results in Release vs. Debug mode.

    Quote Originally Posted by VladimirF View Post
    ... floats have significantly lower precision compared to doubles.
    Forgot to comment on this one. Yes, indeed the type double has 15 digits of precision while an older type float has only 7. But is it really making a big difference in the OP's case?

    You would normally use double over float when dealing with a very small or very large numbers, or when you need to know the difference between, say, the 6th or 7th decimal digit. This may not be that crucial when dealing with most world currencies. (Again, the company's policy has to come into play here.)

    So if the OP's database and/or other storage is coded for the use of float I would not rush to change it over to double. As besides an obvious hassle of converting databases as well as the existing code to a new type (that in itself is fraught with danger) you're also getting a tradeoff of increasing the size of your variables in 2 (i.e. 4 bytes for float and 8 bytes for double). For a large database this can cause a visible increase in its overall size.

    I should also point out that if I was to code a brand new application from scratch I'd probably choose type double over float just for the sake of compatibility with the future technology. But I wouldn't worry if the code is already written to use float's.

  3. #18
    Join Date
    Aug 2000
    Location
    New York, NY, USA
    Posts
    5,656

    Re: Adding doubles together produces different results in Release vs. Debug mode.

    Quote Originally Posted by ahmd View Post
    The multiply and then divide by 1000 part ensures that he doesn't lose the 3-rd decimal place...
    I don't understand that.
    However, I've modified your rounding function to print input parameter (just to compare), and I still see no effect of your transformation:
    Code:
    void printAmountForAUser(double fAmt)
    {
    	_tprintf(_T("%.2f\n"), fAmt);
    	//For a 3-digit precision
    	__int64 ulAmt = (__int64)(fAmt * 1000.0);
    	double fAmtRounded = (double)ulAmt / 1000.0;
    	_tprintf(_T("%.2f\n\n"), fAmtRounded);
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	printAmountForAUser(1237.8599999999999);
    	printAmountForAUser(1237.8549999999999);
    	return 0;
    }
    And result:
    1237.86
    1237.86

    1237.85
    1237.85
    Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
    Convenience and productivity tools for Microsoft Visual Studio:
    FeinWindows - replacement windows manager for Visual Studio, and more...

  4. #19
    Join Date
    Feb 2009
    Location
    Portland, OR
    Posts
    1,488

    Re: Adding doubles together produces different results in Release vs. Debug mode.

    Quote Originally Posted by VladimirF View Post
    However, I've modified your rounding function to print input parameter (just to compare), and I still see no effect of your transformation
    Well, the CRT way of handling %.2f switch for the printf function might have been changed to do the rounding internally since I first wrote this method. If so, then multiplying and then dividing would not be necessary. I'd still stick with it thought, to make sure it works on other (possibly older) platforms.

  5. #20
    Join Date
    Aug 2000
    Location
    New York, NY, USA
    Posts
    5,656

    Re: Adding doubles together produces different results in Release vs. Debug mode.

    Quote Originally Posted by ahmd View Post
    Well, the CRT way of handling %.2f switch for the printf function might have been changed to do the rounding internally since I first wrote this method.
    Please forgive my persistence. I would really like to get it (if there is something here that I can’t understand). I hope that you would also like to get this right.
    Forget printf. Let’s just look at the values in debugger. In this example:
    Code:
    void printAmountForAUser(double fAmt)
    {
    	//For a 3-digit precision
    	__int64 ulAmt = (__int64)(fAmt * 1000.0);
    	double fAmtRounded = (double)ulAmt / 1000.0;
    	if(fAmt == fAmtRounded)
    		_tprintf(_T("EQ\n\n"));
    }
    I got EQ for 1237.8599999999999 (surprised?) and nothing for 1237.8549999999999.
    I then noticed that your initial values didn’t quite make it into doubles.
    I see for the first value
    Code:
    		fAmt	1237.8599999999999	double
    but for the second
    Code:
    		fAmt	1237.8549999999998	double
    First value multiplied by 1000 produced
    Code:
    		ulAmt	1237860	__int64
    Again, surprised?

    But regardless, I am just trying to follow your logic with pen and paper. By multiplying/deviding your doubles you are effectively truncating them. There is NO ROUNDING! What am I missing? Are you using some obscure Intel Processor trick?
    But my guess is that your code only appears to work, and only on that small data sample.
    The behavior will also depend on the floating-point control flags (there was another thread about it today).
    Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
    Convenience and productivity tools for Microsoft Visual Studio:
    FeinWindows - replacement windows manager for Visual Studio, and more...

  6. #21
    Join Date
    Feb 2009
    Location
    Portland, OR
    Posts
    1,488

    Re: Adding doubles together produces different results in Release vs. Debug mode.

    Sure, it's a valid argument. And no, there's no Intel Processor magic either. You might be right though. I posted the code without giving it a second thought. My original idea was that multiplication and division will take care of the last digit rounding, but I see your point. So let's change it to this:
    Code:
    void printAmountForAUser(double fAmt)
    {
    	//For a 3-digit precision
    	__int64 ulAmt = (__int64)(fAmt * 100.0 + 0.5);
    	double fAmtRounded = (double)ulAmt / 100.0;
    	_tprintf(_T("%.2f"), fAmtRounded);
    }
    On the side note.
    As comparison goes, I hope OP realizes that he/she should not be checking floats for equality in a simple == statement. The best alternative would be to use a method like this:
    Code:
    enum AMOUNT_COMPARISON_RESULT{
    	ACR_AMOUNTS_EQUAL = 0,
    	ACR_AMOUNT1_GREATER_THAN_AMOUNT2 = 1,
    	ACR_AMOUNT1_LESS_THAN_AMOUNT2 = -1,
    };
    
    AMOUNT_COMPARISON_RESULT compareTwoAmounts(double fAmt1, double fAmt2)
    {
    	__int64 ulAmt1 = (__int64)(fAmt1 * 100.0 + 0.5);	//Unbiased rounding of the 3rd decimal digit
    	__int64 ulAmt2 = (__int64)(fAmt2 * 100.0 + 0.5);	//Unbiased rounding of the 3rd decimal digit
    	if(ulAmt1 > ulAmt2)
    		return ACR_AMOUNT1_GREATER_THAN_AMOUNT2;
    	else if(ulAmt1 < ulAmt2)
    		return ACR_AMOUNT1_LESS_THAN_AMOUNT2;
    
    	return ACR_AMOUNTS_EQUAL;
    }
    Last edited by ahmd; May 11th, 2011 at 04:10 PM.

  7. #22
    Join Date
    Aug 2000
    Location
    New York, NY, USA
    Posts
    5,656

    Re: Adding doubles together produces different results in Release vs. Debug mode.

    Quote Originally Posted by ahmd View Post
    On the side note.
    As comparison goes, I hope OP realizes that he/she should not be checking floats for equality in a simple == statement.
    Oh, I agree. I used == specifically to see if the bits match exactly (and they did for the first test case).
    Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
    Convenience and productivity tools for Microsoft Visual Studio:
    FeinWindows - replacement windows manager for Visual Studio, and more...

  8. #23
    Join Date
    Jul 2010
    Posts
    37

    Re: Adding doubles together produces different results in Release vs. Debug mode.

    Quote Originally Posted by gageller View Post
    I did the rounding after adding up the individual parts
    You should do the rounding on each value as you add them, not once at the end.

    Consider adding the following 3 values;

    $1.00499999
    $2.00499999
    $3.00499999

    Assuming you want to round and display them to 2 decimal places, and show the total, rounding at the end will give you;
    $1.00
    +$2.00
    +$3.00
    = $6.01

    ($1.00499999 + $2.00499999 + $3.00499999 = 6.01499988)


    If you round as you add each line, the result would be
    $1.00
    +$2.00
    +$3.00
    = $6.00


    $1.00 ($1.00499999 rounded) + $2.00 ($2.00499999 rounded) + $3.00 ($3.00499999 Rounded) = $6.00
    Last edited by petszk; May 11th, 2011 at 09:00 PM.

Page 2 of 2 FirstFirst 12

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