Weird <= operation
-
Hi, I have encountered a problem with a very basic operation. does anybody have any idea about this? Please see sample code below: ////////////////////////////////////////// double a, b; a = 99.99 b = 99.99 if (a <= b){ ::MessageBox(NULL, L"TRUE", L"", MB_OK); } else{ ::MessageBox(NULL, L"FALSE", L"", MB_OK); } ////////////////////////////////////////// somehow, it always display FALSE. Anybody knows how to handle this situation? SDE
-
Hi, I have encountered a problem with a very basic operation. does anybody have any idea about this? Please see sample code below: ////////////////////////////////////////// double a, b; a = 99.99 b = 99.99 if (a <= b){ ::MessageBox(NULL, L"TRUE", L"", MB_OK); } else{ ::MessageBox(NULL, L"FALSE", L"", MB_OK); } ////////////////////////////////////////// somehow, it always display FALSE. Anybody knows how to handle this situation? SDE
Doubles are NOT precise numbers. They are approximate representations. Whenever you need to compare doubles (or check if zero), you need to do approximate math, using an acceptable number of precision digits to your app. An example is below:
BOOL IsDoubleZero(double dVal)
{
if (dVal < 0.000001 && dVal > -0.000001)
return TRUE;return FALSE;
}BOOL AreDoublesEqual(double dVal1, double dVal2)
{
doubld dDiff = dVal1 - dVal2;
if (dDiff < 0.000001 && dDiff > -0.000001)
return TRUE;return FALSE;
}onwards and upwards...
-
Doubles are NOT precise numbers. They are approximate representations. Whenever you need to compare doubles (or check if zero), you need to do approximate math, using an acceptable number of precision digits to your app. An example is below:
BOOL IsDoubleZero(double dVal)
{
if (dVal < 0.000001 && dVal > -0.000001)
return TRUE;return FALSE;
}BOOL AreDoublesEqual(double dVal1, double dVal2)
{
doubld dDiff = dVal1 - dVal2;
if (dDiff < 0.000001 && dDiff > -0.000001)
return TRUE;return FALSE;
}onwards and upwards...
Wow - never knew that. What about floats? Same thing? Hope so else I just screwed up an interview question! ********************************************* The sooner you fall behind, the longer you have to catch up.
-
Wow - never knew that. What about floats? Same thing? Hope so else I just screwed up an interview question! ********************************************* The sooner you fall behind, the longer you have to catch up.
-
Angel1058 wrote: What about floats? Same thing? Yes. /ravi My new year's resolution: 2048 x 1536 Home | Articles | Freeware | Music ravib@ravib.com
I find that absolutely astonishing - you can't compare two doubles or floats for equality? So all these financial and scientific calculations using massive numbers with loads of decimal places aren't accurate - they are approximations?!? It's not that I am doubting anything written here but I still find that amazing. 99.99 isn't guaranteed to equal 99.99. Are there any precise types then? ********************************************* The sooner you fall behind, the longer you have to catch up.
-
I find that absolutely astonishing - you can't compare two doubles or floats for equality? So all these financial and scientific calculations using massive numbers with loads of decimal places aren't accurate - they are approximations?!? It's not that I am doubting anything written here but I still find that amazing. 99.99 isn't guaranteed to equal 99.99. Are there any precise types then? ********************************************* The sooner you fall behind, the longer you have to catch up.
Angel1058 wrote: So all these financial and scientific calculations ... they are approximations?!? Correct. Most scientific and financial applications (including my hack TakeStock[^] (forgive the shameless plug - but after all, it is freeware) will instead store floating point numbers as an aggregation of integers (which can be accurately compared). So a bank balance of $12,345,678.90123 will instead be stored as the integer value 1,234,567,890,123 "milli cents". Since the number of mCents could be extremely large, you need store this value in a collection of
int
s. In the 70's and early 80's, many programmers used PL/1 which included aDECIMAL
data structure for exactly this kind of thing. Microsoft provides theCURRENCY
[^] type that suffices for most financial calculations. Hope this helps! /ravi My new year's resolution: 2048 x 1536 Home | Articles | Freeware | Music ravib@ravib.com -
Hi, I have encountered a problem with a very basic operation. does anybody have any idea about this? Please see sample code below: ////////////////////////////////////////// double a, b; a = 99.99 b = 99.99 if (a <= b){ ::MessageBox(NULL, L"TRUE", L"", MB_OK); } else{ ::MessageBox(NULL, L"FALSE", L"", MB_OK); } ////////////////////////////////////////// somehow, it always display FALSE. Anybody knows how to handle this situation? SDE
Is this your actual code? What cmpiler, what settings do you use? While it is true what was said - floats and doubles are not accurate representations - a simple assignment like yours typically is ok. (And your ode with default debug/release settings outputs "TRUE" for me). float and double both use a limited number of digits, certain numbers e.g 1/3, cannot berepresented accurately this way. Also, during calculations, final digits simply get lost. So comparing *results* as replied is a must. However, you should also consider the alternative:
bool IsEqualRel(double a, double b, double eps = 1e-5)
{
_ASSERTE(a!= 0 && b != 0);
if (a==b) return true;
if (a<0 != b<0) return false;
return fabs((a-b)/a+b)) < eps;
}bool IsZero(double a, double eps = 1e-5)
{
return a==0 || fabs(a) < eps;
}which works for all magnitudes except comparison to zero (that's why the separate IsZero function). With the absolute posted by the other guy, 1e-27 == 100e-27 and 10000000000000 != 10000000000001 which is often not what you need when working with numbers in this range.
I never really know a killer from a savior
boost your code || Fold With Us! || sighist | doxygen -
Doubles are NOT precise numbers. They are approximate representations. Whenever you need to compare doubles (or check if zero), you need to do approximate math, using an acceptable number of precision digits to your app. An example is below:
BOOL IsDoubleZero(double dVal)
{
if (dVal < 0.000001 && dVal > -0.000001)
return TRUE;return FALSE;
}BOOL AreDoublesEqual(double dVal1, double dVal2)
{
doubld dDiff = dVal1 - dVal2;
if (dDiff < 0.000001 && dDiff > -0.000001)
return TRUE;return FALSE;
}onwards and upwards...