You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

151 lines
2.9 KiB

1 year ago
  1. /* Display structure of floating-point numbers */
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. float strtof(const char *nptr, char **endptr);
  5. #define FLOAT_SIZE 32
  6. #define FRAC_SIZE 23
  7. #define EXP_SIZE 8
  8. #define BIAS ((1<<(EXP_SIZE-1))-1)
  9. #define FRAC_MASK ((1<<FRAC_SIZE)-1)
  10. #define EXP_MASK ((1<<EXP_SIZE)-1)
  11. /* Floating point helpers */
  12. unsigned f2u(float f)
  13. {
  14. union {
  15. unsigned u;
  16. float f;
  17. } v;
  18. v.u = 0;
  19. v.f = f;
  20. return v.u;
  21. }
  22. static float u2f(unsigned u)
  23. {
  24. union {
  25. unsigned u;
  26. float f;
  27. } v;
  28. v.u = u;
  29. return v.f;
  30. }
  31. /* Get exponent */
  32. unsigned get_exp(unsigned uf)
  33. {
  34. return (uf>>FRAC_SIZE) & EXP_MASK;
  35. }
  36. /* Get fraction */
  37. unsigned get_frac(unsigned uf)
  38. {
  39. return uf & FRAC_MASK;
  40. }
  41. /* Get sign */
  42. unsigned get_sign(unsigned uf)
  43. {
  44. return (uf>>(FLOAT_SIZE-1)) & 0x1;
  45. }
  46. void show_float(unsigned uf)
  47. {
  48. float f = u2f(uf);
  49. unsigned exp = get_exp(uf);
  50. unsigned frac = get_frac(uf);
  51. unsigned sign = get_sign(uf);
  52. printf("\nFloating point value %.10g\n", f);
  53. printf("Bit Representation 0x%.8x, sign = %x, exponent = 0x%.2x, fraction = 0x%.6x\n",
  54. uf, sign, exp, frac);
  55. if (exp == EXP_MASK) {
  56. if (frac == 0) {
  57. printf("%cInfinity\n", sign ? '-' : '+');
  58. } else
  59. printf("Not-A-Number\n");
  60. } else {
  61. int denorm = (exp == 0);
  62. int uexp = denorm ? 1-BIAS : exp - BIAS;
  63. int mantissa = denorm ? frac : frac + (1<<FRAC_SIZE);
  64. float fman = (float) mantissa / (float) (1<<FRAC_SIZE);
  65. printf("%s. %c%.10f X 2^(%d)\n",
  66. denorm ? "Denormalized" : "Normalized",
  67. sign ? '-' : '+',
  68. fman, uexp);
  69. }
  70. }
  71. /* Extract hex/decimal/or float value from string */
  72. static int get_num_val(char *sval, unsigned *valp) {
  73. char *endp;
  74. /* See if it's an integer or floating point */
  75. int ishex = 0;
  76. int isfloat = 0;
  77. int i;
  78. for (i = 0; sval[i]; i++) {
  79. switch (sval[i]) {
  80. case 'x':
  81. case 'X':
  82. ishex = 1;
  83. break;
  84. case 'e':
  85. case 'E':
  86. if (!ishex)
  87. isfloat = 1;
  88. break;
  89. case '.':
  90. isfloat = 1;
  91. break;
  92. default:
  93. break;
  94. }
  95. }
  96. if (isfloat) {
  97. float fval = strtof(sval, &endp);
  98. if (!*endp) {
  99. *valp = *(unsigned *) &fval;
  100. return 1;
  101. }
  102. return 0;
  103. } else {
  104. long long int llval = strtoll(sval, &endp, 0);
  105. long long int upperbits = llval >> 31;
  106. /* will give -1 for negative, 0 or 1 for positive */
  107. if (valp && (upperbits == 0 || upperbits == -1 || upperbits == 1)) {
  108. *valp = (unsigned) llval;
  109. return 1;
  110. }
  111. return 0;
  112. }
  113. }
  114. void usage(char *fname) {
  115. printf("Usage: %s val1 val2 ...\n", fname);
  116. printf("Values may be given as hex patterns or as floating point numbers\n");
  117. exit(0);
  118. }
  119. int main(int argc, char *argv[])
  120. {
  121. int i;
  122. unsigned uf;
  123. if (argc < 2)
  124. usage(argv[0]);
  125. for (i = 1; i < argc; i++) {
  126. char *sval = argv[i];
  127. if (get_num_val(sval, &uf)) {
  128. show_float(uf);
  129. } else {
  130. printf("Invalid 32-bit number: '%s'\n", sval);
  131. usage(argv[0]);
  132. }
  133. }
  134. return 0;
  135. }