1,105,633 Community Members

Floating point multiplication, precision issues

Member Avatar
thekashyap
Practically a Posting Shark
809 posts since Feb 2007
Reputation Points: 193 [?]
Q&As Helped to Solve: 77 [?]
Skill Endorsements: 0 [?]
 
0
 

Hello *,
I was writing an assert() stmt when I realized the following (see code). Can anyone explain why/how. My final aim is to be able to write an assert stmt for verifying that my function (a demo function) works fine.

I heard from someone that there are special assert-macros/comparision-operators for floating point arithmatic. Is it trur?

#include <iostream>

using namespace std ;

int main()
{
    double a = 2.2, b = 1234.5678 ;
    double c = a * b ;
    //accorging to windows' calc.exe 2.2 * 1234.5678 = 2716.04916
    //which of course is correct if you multiply manually
    if( 2716.04916 == c )
        cout << "Cacl.exe and C++ give same results" << endl ;
    else
        cout << "Cacl.exe gives 2716.04916 and C++ gives "<< c << endl ;

    //so we know that assert( 2716.04916 == c ) will fail for sure.

    return 0;
}

When I run the code (compiled and run on VC 6.0) this is the output I get:
------------------------------------------------------------------
Cacl.exe gives 2716.04916 and C++ gives 2716.05
Press any key to continue
------------------------------------------------------------------

Member Avatar
Ancient Dragon
Achieved Level 70
27,637 posts since Aug 2005
Reputation Points: 5,232 [?]
Q&As Helped to Solve: 3,037 [?]
Skill Endorsements: 115 [?]
Team Colleague
Featured
Sponsor
 
0
 

line 11 may or may not work even though it would appear to us that it should. The reason is because many floats can not be represented exactly in memory due to the way IEEE math works. The best you can do is check for a range of values instead of an exact value.

Member Avatar
vijayan121
Posting Virtuoso
1,769 posts since Dec 2006
Reputation Points: 1,097 [?]
Q&As Helped to Solve: 329 [?]
Skill Endorsements: 16 [?]
 
0
 

a. you should be able to get a more accurate output by using cout << fixed << setprecision(5).

b. the accuracy of the mantissa of a floating point value on a c++ implementation can be gauged from std::numeric_limits<float>::digits.
rough accuracy for reasonable small values would be within += std::numeric_limits<float>::epsilon()

Member Avatar
thekashyap
Practically a Posting Shark
809 posts since Feb 2007
Reputation Points: 193 [?]
Q&As Helped to Solve: 77 [?]
Skill Endorsements: 0 [?]
 
0
 

Thanks guys.. Indeed the problem is due to the way a double/float value is represented in memory..

Here is a nice link I found describing how to do floating point comparisions..

Here is updated code for insight into the memory:

#include <iostream>

using namespace std ;

template< typename _T >
void print_hex( const _T* d )
{
    const unsigned char* ar = (const unsigned char*) d ;
    for( int i = 0; i < sizeof(_T); i++ )
        printf("%X ", ar[i]) ;
    putch('\n') ;
}

int main()
{
    double a = 2.2, b = 1234.5678 ;
    double c, d ;

    memset(&c, 0, sizeof(double)) ;
    memset(&d, 0, sizeof(double)) ;

    cout << "After memset, before assignment\n" ;
    print_hex(&c) ;
    print_hex(&d) ;

    c = a * b ;
    d = 2716.04916 ;

    cout << "\nAfter assignment\n" ;
    print_hex(&c) ;
    print_hex(&d) ;

    //accorging to windows' calc.exe 2.2 * 1234.5678 = 2716.04916
    //which of course is correct if you multiply manually
    if( d == c )
        cout << "Cacl.exe and C++ give same results" << endl ;
    else
        printf("\n\"operator ==\" says %f and %f are different numbers.\n\n" ,d ,c );

    return 0;
}

And here is my output with VS 6.0 on Intel.
------------------------------------------
After memset, before assignment
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

After assignment
8C E0 7F 2B 19 38 A5 40
8B E0 7F 2B 19 38 A5 40

"operator ==" says 2716.049160 and 2716.049160 are different numbers.

Press any key to continue
------------------------------------------

Question Answered as of 2 Years Ago by Ancient Dragon and vijayan121
You
This question has already been solved: Start a new discussion instead
Post:
Start New Discussion
Tags Related to this Article