code_junkie

Comparing IEEE floats and doubles for equality

Nov 10th, 2011
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.33 KB | None | 0 0
  1. bool is_nan(float f)
  2. {
  3. return (*reinterpret_cast<unsigned __int32*>(&f) & 0x7f800000) == 0x7f800000 && (*reinterpret_cast<unsigned __int32*>(&f) & 0x007fffff) != 0;
  4. }
  5.  
  6. bool is_finite(float f)
  7. {
  8. return (*reinterpret_cast<unsigned __int32*>(&f) & 0x7f800000) != 0x7f800000;
  9. }
  10.  
  11. // if this symbol is defined, NaNs are never equal to anything (as is normal in IEEE floating point)
  12. // if this symbol is not defined, NaNs are hugely different from regular numbers, but might be equal to each other
  13. #define UNEQUAL_NANS 1
  14. // if this symbol is defined, infinites are never equal to finite numbers (as they're unimaginably greater)
  15. // if this symbol is not defined, infinities are 1 ULP away from +/- FLT_MAX
  16. #define INFINITE_INFINITIES 1
  17.  
  18. // test whether two IEEE floats are within a specified number of representable values of each other
  19. // This depends on the fact that IEEE floats are properly ordered when treated as signed magnitude integers
  20. bool equal_float(float lhs, float rhs, unsigned __int32 max_ulp_difference)
  21. {
  22. #ifdef UNEQUAL_NANS
  23. if(is_nan(lhs) || is_nan(rhs))
  24. {
  25. return false;
  26. }
  27. #endif
  28. #ifdef INFINITE_INFINITIES
  29. if((is_finite(lhs) && !is_finite(rhs)) || (!is_finite(lhs) && is_finite(rhs)))
  30. {
  31. return false;
  32. }
  33. #endif
  34. signed __int32 left(*reinterpret_cast<signed __int32*>(&lhs));
  35. // transform signed magnitude ints into 2s complement signed ints
  36. if(left < 0)
  37. {
  38. left = 0x80000000 - left;
  39. }
  40. signed __int32 right(*reinterpret_cast<signed __int32*>(&rhs));
  41. // transform signed magnitude ints into 2s complement signed ints
  42. if(right < 0)
  43. {
  44. right = 0x80000000 - right;
  45. }
  46. if(static_cast<unsigned __int32>(std::abs(left - right)) <= max_ulp_difference)
  47. {
  48. return true;
  49. }
  50. return false;
  51. }
  52.  
  53. bool is_equals(float A, float B,
  54. float maxRelativeError, float maxAbsoluteError)
  55. {
  56.  
  57. if (fabs(A - B) < maxAbsoluteError)
  58. return true;
  59.  
  60. float relativeError;
  61. if (fabs(B) > fabs(A))
  62. relativeError = fabs((A - B) / B);
  63. else
  64. relativeError = fabs((A - B) / A);
  65.  
  66. if (relativeError <= maxRelativeError)
  67. return true;
  68.  
  69. return false;
  70. }
  71.  
  72. #include <iostream>
  73.  
  74. using namespace std;
  75.  
  76.  
  77. int main()
  78. {
  79. float a = 1.0;
  80. float b = 0.0;
  81.  
  82. for(int i=0;i<10;++i)
  83. {
  84. b+=0.1;
  85. }
  86.  
  87. if(a != b)
  88. {
  89. cout << "Something is wrong" << endl;
  90. }
  91.  
  92. return 1;
  93. }
Add Comment
Please, Sign In to add comment