Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <math.h>
- #include <errno.h>
- #if defined(__LP64__) || defined(_LP64)
- # define BUILD_64 1
- #endif
- /* constants for word and double-word size */
- #define WDSZ 64
- #define DWSZ 128
- inline int getmsb (unsigned long x);
- char *fmt_binstr (unsigned long n, unsigned char sz, unsigned char szs, char sep);
- char *binstr (unsigned long n);
- char *fpfrc_bin (float fvalue);
- void show_fltmem (float f);
- void show_ieee754str (char *s);
- void show_ieee754 (float f);
- float xstrtof (char *str);
- char *form_ieee754SPstr (int sign, char *exp, char *dec, char *frac);
- int main (int argc, char** argv) {
- if (argc < 2) {
- fprintf (stderr, "error: insufficient input. Usage: %s float\n", argv[0]);
- return 1;
- }
- char *dp = strchr (argv[1], '.'); /* pointer to decimal point */
- int dec = atoi (argv[1]); /* integer of decimal part */
- int frc = (dp) ? atoi (dp + 1) : 0; /* integer of fraction part */
- /* output string input values */
- printf ("\nString Values:\n");
- printf (" string : %s\n whole : %d\n fraction : %d\n\n", argv[1], dec, frc);
- float fvalue = xstrtof (argv[1]);
- float ffrc = fvalue - dec;
- int signbit = (fvalue >= 0) ? 0 : 1;
- /* output float input values */
- printf ("Float Values:\n");
- printf (" decimal : %d\n fraction : %f\n\n", dec, ffrc);
- char *fstring = fpfrc_bin (fvalue); /* fraction part in binary */
- char *bs = binstr ((unsigned long) dec); /* decimal part in binary */
- /* output binary values decimal part/fraction part */
- printf ("Binary Values:\n");
- printf (" decimal : %s\n fraction : %s\n sign bit : %d\n\n", bs, fstring, signbit);
- /* quick hack of exp bias, biased value, conversion to binary */
- int bias = (int) strlen (bs) - 1;
- int biasexp = 127+bias;
- char *binexp = binstr ((unsigned long) biasexp);
- /* output summary of biased IEEE-754 exponent */
- printf ("Normalization for biased exponent:\n");
- printf ("\n %s.%s => %s.%s%s\n\n", bs, fstring, "1", (bs+1), fstring);
- printf (" exponent bias: %d\n unbiased exponent: 127\n", bias);
- printf (" __________________+____\n\n");
- printf (" biased exponent: %3d\n binary exponent: %s\n\n", biasexp, binexp);
- /* output summary of IEEE-754 mantissa */
- printf ("Conversion to 'hidden bit' format to form mantissa:\n\n");
- printf (" %s.%s%s => %s%s\n\n", "1", (bs+1), fstring, (bs+1), fstring);
- /* form IEEE-754 binary representation from values computed */
- char *ieee754str = form_ieee754SPstr (signbit, binexp, bs, fstring);
- /* output formatted complete IEEE-754 binary - from computed values above */
- printf ("IEEE-754 Single Precision Floating Point Representation (caclulated value)\n\n");
- show_ieee754str (ieee754str);
- /* output formatted complete IEEE-754 binary - from float value in memory */
- printf ("IEEE-754 Single Precision Floating Point Representation (memory value)\n\n");
- show_ieee754 (fvalue);
- /* output float, binary and integer equivalent */
- show_fltmem (fvalue);
- if (bs) free (bs);
- if (binexp) free (binexp);
- if (ieee754str) free (ieee754str);
- return 0;
- }
- /** single-precision float in memory
- * output the float, equivalent unsigned int, and
- * binary representation of the number in memory
- */
- void show_fltmem (float f)
- {
- unsigned int i = *(unsigned int *)&f;
- printf ("\nRepresentations of float value in memory:\n\n");
- printf (" The float value entered : %f\n\n", f);
- printf (" binary value in memory : %s\n\n", fmt_binstr (i, 32, 8, '-'));
- printf (" bits as unsigned int : %u\n\n", i);
- }
- /** most significant bit.
- * return the 0-based most significant bit for any
- * unsigned value using the bit-scan-right assembly
- * directive.
- */
- inline int getmsb (unsigned long x)
- {
- #ifdef BUILD_64
- asm ("bsrq %0, %0" : "=r" (x) : "0" (x));
- #else
- asm ("bsr %0, %0" : "=r" (x) : "0" (x));
- #endif
- return x;
- }
- /** returns pointer to formatted binary representation of 'n' zero padded to 'sz'.
- * returns pointer to string contianing formatted binary representation of
- * unsigned 64-bit (or less ) value zero padded to 'sz' digits with char
- * 'sep' placed every 'szs' digits. (e.g. 10001010 -> 1000-1010).
- */
- char *fmt_binstr (unsigned long n, unsigned char sz, unsigned char szs, char sep) {
- static char s[DWSZ + 1] = {0};
- char *p = s + DWSZ;
- unsigned char i;
- for (i = 0; i < sz; i++) {
- p--;
- if (i > 0 && szs > 0 && i % szs == 0)
- *p-- = sep;
- *p = (n >> i & 1) ? '1' : '0';
- }
- return p;
- }
- /** returns an allocated string containing unpadded binary
- * representation of the integer value 'n'. This value must
- * be assigned to a pointer and freed to prevent leaks.
- */
- char *binstr (unsigned long n)
- {
- unsigned char msb = getmsb (n);
- char *s = calloc (msb + 2, sizeof *s);
- char *p = s + msb;
- unsigned char i;
- for (i = 0; i < msb+1; i++) {
- *p-- = (n >> i & 1) ? '1' : '0';
- }
- return s;
- }
- /** return string containing binary representation of fraction
- * The function takes a float as an argument and computes the
- * binary representation of the fractional part of the float,
- * On success, the function returns a null-terminated string
- * containing the binary value, or NULL otherwise. MAXD of 24
- * (23 + null-term) for Single-Precision mantissa, 53
- * (52 + null-term) for Double-Precision mantissa.
- */
- char *fpfrc_bin (float fvalue)
- {
- float fv = fvalue - (int)fvalue;
- int MAXD = 24;
- char *fvs = calloc (MAXD, sizeof *fvs);
- if (!fvs) {
- fprintf (stderr, "%s()_error: allocation failed.\n", __func__);
- return NULL;
- }
- char *p = fvs;
- unsigned char it = 0;
- while (fv > 0 && it < MAXD)
- {
- fv = fv * 2.0;
- *p++ = ((int)fv) ? '1' : '0';
- fv = ((int)fv >= 1) ? fv - 1.0 : fv;
- it++;
- }
- return fvs;
- }
- /** formatted output of ieee-754 representation of float from binary string.
- */
- void show_ieee754str (char *s)
- {
- printf (" ");
- while (*s)
- printf (" %c", *s++);
- printf ("\n");
- printf (" |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|\n");
- printf (" |s| exp | mantissa |\n\n");
- }
- /** formatted output of ieee-754 representation of float from stored value.
- */
- void show_ieee754 (float f)
- {
- printf (" ");
- int i = 32;
- while (i) {
- i--;
- printf ("%d ", ((*(int *)&f >> i) & 0x1));
- }
- printf ("\n");
- printf (" |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|\n");
- printf (" |s| exp | mantissa |\n\n");
- }
- /** string to float with error checking. */
- float xstrtof (char *str)
- {
- char *endptr = NULL;
- errno = 0;
- float val = strtof (str, &endptr);
- /* Check for various possible errors */
- if ((errno == ERANGE && (val == HUGE_VALF || val == HUGE_VALL)) ||
- (errno != 0 && val == 0)) {
- perror ("strtof");
- exit (EXIT_FAILURE);
- }
- if (endptr == str) {
- fprintf (stderr, "No digits were found\n");
- exit (EXIT_FAILURE);
- }
- return val;
- }
- /** form IEEE-754 binary representation from computed values for the
- * sign bit, biased exponent binary string, decimal binary string, and
- * fractional binary string, forming the 23-bit mantissa from the decimal
- * and fractional strings, filling with '0' as needed. An allocated
- * string containing the IEEE-754 Single-Precision representation is
- * returned.
- */
- char *form_ieee754SPstr (int sign, char *exp, char *dec, char *frac)
- {
- char *str = calloc (33, sizeof *str);
- char *p = str + 1;
- char *sp = dec + 1; /* leading 1 - hidden bit */
- size_t fsl = strlen (frac); /* length of fractional str */
- size_t manbits = fsl + strlen (sp); /* available mantissa bits */
- size_t mdiff = 23 - manbits; /* diff from required 23 */
- *str = (sign == 0) ? '0' : '1'; /* set sign bit in string */
- memcpy (p, exp, 8); /* set biased exponent */
- p += 8;
- while (*sp) { *p = *sp++; p++; }; /* mantissa - decimal bits */
- if (manbits < 23) /* test < 23 bits available */
- {
- memcpy (p, frac, fsl); /* copy fractional bits */
- p += fsl; /* increment pointer */
- register size_t it = 0;
- if (mdiff > 0) /* fill remaining mantissa */
- for (it = 0; it < mdiff; it++)
- {
- *p = '0';
- p++;
- }
- }
- else
- {
- memcpy (p, frac, 23); /* fill mantissa w/23 bits */
- }
- return str;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement