fork download
  1. #include <cmath>
  2. #include <cstddef>
  3. #include <cstdint>
  4. #include <cstdio>
  5. #include <limits>
  6. #include <utility>
  7.  
  8.  
  9. union Float_t
  10. {
  11. Float_t(float num = 0.0f) : f(num) {}
  12.  
  13. bool Negative() const { return (i >> 31) != 0; }
  14. std::int32_t RawMantissa() const { return i & ((1 << 23) - 1); }
  15. std::int32_t RawExponent() const { return (i >> 23) & 0xFF; }
  16.  
  17. std::int32_t i;
  18. float f;
  19.  
  20. struct
  21. {
  22. std::uint32_t mantissa : 23;
  23. std::uint32_t exponent : 8;
  24. std::uint32_t sign : 1;
  25. } parts;
  26. };
  27.  
  28.  
  29. template<typename T>
  30. unsigned int ulpDistance(T value1, T value2)
  31. {
  32. // Simplified version not treating special cases from
  33. // http://stackoverflow.com/questions/13940316/floating-point-comparison-revisited
  34.  
  35. int minExponent, maxExponent;
  36. T minSignificand = std::frexp(value1, &minExponent);
  37. T maxSignificand = std::frexp(value2, &maxExponent);
  38. if (minExponent > maxExponent) {
  39. std::swap(minSignificand, maxSignificand);
  40. std::swap(minExponent, maxExponent);
  41. }
  42.  
  43. const T scaledMinSignificand = std::ldexp(
  44. minSignificand, minExponent - maxExponent
  45. );
  46.  
  47. return 2 * std::abs(maxSignificand - scaledMinSignificand) /
  48. std::numeric_limits<T>::epsilon();
  49. }
  50.  
  51.  
  52. int main(int argc, char **argv)
  53. {
  54. Float_t first = 1.999999f;
  55. Float_t number = first.f;
  56.  
  57. do
  58. {
  59. std::printf(
  60. "float(%1.8e), int(0x%08X), exponent(%d), mantissa(0x%06X)\n",
  61. number.f, number.i,
  62. number.parts.exponent, number.parts.mantissa
  63. );
  64.  
  65. if (ulpDistance(first.f, number.f) != number.i - first.i) {
  66. std::printf(" %d != %d\n",
  67. ulpDistance(first.f, number.f), number.i - first.i);
  68. }
  69.  
  70. number.i += 1;
  71. } while (number.f < 2.000001f);
  72.  
  73. return 0;
  74. }
  75.  
Success #stdin #stdout 0s 3296KB
stdin
Standard input is empty
stdout
float(1.99999905e+00), int(0x3FFFFFF8), exponent(127), mantissa(0x7FFFF8)
float(1.99999917e+00), int(0x3FFFFFF9), exponent(127), mantissa(0x7FFFF9)
float(1.99999928e+00), int(0x3FFFFFFA), exponent(127), mantissa(0x7FFFFA)
float(1.99999940e+00), int(0x3FFFFFFB), exponent(127), mantissa(0x7FFFFB)
float(1.99999952e+00), int(0x3FFFFFFC), exponent(127), mantissa(0x7FFFFC)
float(1.99999964e+00), int(0x3FFFFFFD), exponent(127), mantissa(0x7FFFFD)
float(1.99999976e+00), int(0x3FFFFFFE), exponent(127), mantissa(0x7FFFFE)
float(1.99999988e+00), int(0x3FFFFFFF), exponent(127), mantissa(0x7FFFFF)
float(2.00000000e+00), int(0x40000000), exponent(128), mantissa(0x000000)
  4 != 8
float(2.00000024e+00), int(0x40000001), exponent(128), mantissa(0x000001)
  5 != 9
float(2.00000048e+00), int(0x40000002), exponent(128), mantissa(0x000002)
  6 != 10
float(2.00000072e+00), int(0x40000003), exponent(128), mantissa(0x000003)
  7 != 11