In the code below I use mpf_add
to add the string representation of two floating values. What I don't understand at this point is why 2.2 + 3.2 = 5.39999999999999999999999999999999999999
. I would have thought that gmp
was smart enough to give 5.4
.
What am I not comprehending about how gmp does floats?
(BTW, when I first wrote this I wasn't sure how to insert a decimal point, thus the plus/minus digit stuff at the end)
BSTR __stdcall FBIGSUM(BSTR p1, BSTR p2 ) {
USES_CONVERSION;
F(n1);
F(n2);
F(res);
LPSTR sNum1 = W2A( p1 );
LPSTR sNum2 = W2A( p2 );
mpf_set_str( n1, sNum1, 10 );
mpf_set_str( n2, sNum2, 10 );
mpf_add( res, n1, n2 );
char * buff = (char *) _alloca( 1024 );
char expBuffer[ 20 ];
mp_exp_t exp;
mpf_get_str(buff, &exp, 10, 0, res);
char * temp = ltoa( (long) exp, expBuffer, 10 );
if (exp >= 0) {
strcat(buff, "+" );
}
strcat(buff, expBuffer );
BSTR bResult = _com_util::ConvertStringToBSTR( buff );
return bResult;
}
This is because of the inherent error of using floating-point arithmetic in a binary environment.
See the IEEE 754 standard for more information.
What warren said.
You might have better results if you use binary coded decimal instead of floating point numbers, although I can't really direct you to any libraries for that.
I eventually ended up answering this myself. The solution for me was to do in code what I used to do in school. The method works like this:
2.1
and3.457
, 'normalise' the first one to2.100
. Keep a record of the number of digits that are to the right of the decimal, in this case, three.mpz_add
to add the two numbers, which have now become2100
and3457
. The result is5557
.5.557
.I prototyped the solution in VBScript (below)
and finally in Visual C++ (below).
I accept that the C is a bit ... well ... dodgy, so please feel free to critique it. All helpful comments gratefully received.
I went on from here to implement FSUB and FMUL as well. FDIV was not nearly so satisfying, ending up in three versions and using rational numbers.