fork download
  1. #include <stdio.h>
  2. #include <limits.h>
  3.  
  4. #if UINT_MAX >= 0xFFFFFFFF
  5. typedef unsigned uint32;
  6. #else
  7. typedef unsigned long uint32;
  8. #endif
  9.  
  10. #define C_ASSERT(expr) extern char CAssertExtern[(expr)?1:-1]
  11.  
  12. // Ensure uint32 is exactly 32-bit
  13. C_ASSERT(sizeof(uint32) * CHAR_BIT == 32);
  14.  
  15. // Ensure float has the same number of bits as uint32, 32
  16. C_ASSERT(sizeof(uint32) == sizeof(float));
  17.  
  18. double Ieee754SingleDigits2DoubleCheat(const char s[32])
  19. {
  20. uint32 v;
  21. float f;
  22. unsigned i;
  23. char *p1 = (char*)&v, *p2 = (char*)&f;
  24.  
  25. // Collect binary digits into an integer variable
  26. v = 0;
  27. for (i = 0; i < 32; i++)
  28. v = (v << 1) + (s[i] - '0');
  29.  
  30. // Copy the bits from the integer variable to a float variable
  31. for (i = 0; i < sizeof(f); i++)
  32. *p2++ = *p1++;
  33.  
  34. return f;
  35. }
  36.  
  37. double Ieee754SingleDigits2DoubleNoCheat(const char s[32])
  38. {
  39. double f;
  40. int sign, exp;
  41. uint32 mant;
  42. int i;
  43.  
  44. // Do you really need strto*() here?
  45. sign = s[0] - '0';
  46.  
  47. // Do you really need strto*() or pow() here?
  48. exp = 0;
  49. for (i = 1; i <= 8; i++)
  50. exp = exp * 2 + (s[i] - '0');
  51.  
  52. // Remove the exponent bias
  53. exp -= 127;
  54.  
  55. // Should really check for +/-Infinity and NaNs here
  56.  
  57. if (exp > -127)
  58. {
  59. // Normal(ized) numbers
  60. mant = 1; // The implicit "1."
  61. // Account for "1." being in bit position 23 instead of bit position 0
  62. exp -= 23;
  63. }
  64. else
  65. {
  66. // Subnormal numbers
  67. mant = 0; // No implicit "1."
  68. exp = -126; // See your IEEE-54 formulas
  69. // Account for ".1" being in bit position 22 instead of bit position -1
  70. exp -= 23;
  71. }
  72.  
  73. // Or do you really need strto*() or pow() here?
  74. for (i = 9; i <= 31; i++)
  75. mant = mant * 2 + (s[i] - '0');
  76.  
  77. f = mant;
  78.  
  79. // Do you really need pow() here?
  80. while (exp > 0)
  81. f *= 2, exp--;
  82.  
  83. // Or here?
  84. while (exp < 0)
  85. f /= 2, exp++;
  86.  
  87. if (sign)
  88. f = -f;
  89.  
  90. return f;
  91. }
  92.  
  93. int main(void)
  94. {
  95. printf("%+g\n", Ieee754SingleDigits2DoubleCheat("110000101100010010000000000000000"));
  96. printf("%+g\n", Ieee754SingleDigits2DoubleNoCheat("010000101100010010000000000000000"));
  97. printf("%+g\n", Ieee754SingleDigits2DoubleCheat("000000000100000000000000000000000"));
  98. printf("%+g\n", Ieee754SingleDigits2DoubleNoCheat("100000000100000000000000000000000"));
  99. printf("%+g\n", Ieee754SingleDigits2DoubleCheat("000000000000000000000000000000000"));
  100. printf("%+g\n", Ieee754SingleDigits2DoubleNoCheat("000000000000000000000000000000000"));
  101. return 0;
  102. }
  103.  
Success #stdin #stdout 0s 1832KB
stdin
Standard input is empty
stdout
-98.25
+98.25
+5.87747e-39
-5.87747e-39
+0
+0