cbyte-shiftingmantissa

I want to know how to approach these functions in C. I have tried solving them but failed



#include    <stdlib.h>
#include    <stdio.h>
#include    <float.h>


//--            Sign related constants              --//

//  PURPOSE:  To be the mask to only keep the sign bit.
const int   SIGN_MASK       = 0x80000000;

//  PURPOSE:  To tell how many bits to shift the sign bit from the least
//  signficant position to where the sign bit belongs.
const int   SIGN_SHIFT      = 31;


//--            Exponent related constants          --//


//  PURPOSE:  To be the mask to only keep the exponent bit field.
const int   EXPONENT_MASK       = 0x7F800000;

//  PURPOSE:  To tell how many bits to shift the exponent bit field from the
//  least signficant position to where the exponent bit field belongs.
const int   EXPONENT_SHIFT      = 23;

//  PURPOSE:  To tell the 'bias' of the exponent bit field:
//  (powerOf2) = (exponentBitPattern) - EXPONENT_BIAS
const int   EXPONENT_BIAS       = 127;

//  PURPOSE:  To tell the exponent bit pattern for denormalized numbers
//  (including 0.0).
const int   EXPONENT_DENORMALIZED_BIT_PATTERN
                    = 0x00;

//  PURPOSE:  To tell the exponent bit pattern for 'infinity' and
//  'not-a-number'.
const int   EXPONENT_INFINITE_BIT_PATTERN
                    = 0xFF;

//  PURPOSE:  To tell the power of 2 for 'infinity' and 'not-a-number'.
const int    INFINITE_POWER_OF_2    = +128;

//  PURPOSE:  To tell the power of 2 for denormalized numbers (including 0.0):
const int    DENORMALIZED_POWER_OF_2= -127;


//--            Mantissa related constants          --//

//  PURPOSE:  To tell the mask to only keep the mantissa bit field.
const int   MANTISSA_MASK       = 0x007FFFFF;

//  PURPOSE:  To tell how many bits to shift the mantissa bit field from the
//  least signficant position to where the mantissa bit field belongs.
const int   MANTISSA_SHIFT      = 0;

//  PURPOSE:  To tell position of the hidden bit in the mantissa bit field.
const int   MANTISSA_HIDDEN_BIT = 0x00800000;

//  PURPOSE:  To tell the bits too high for the mantissa to occupy.
const int   MANTISSA_TOO_BIG_FIELD  = 0xFF000000;


//--            Functions of program:               --//

//  PURPOSE:  To return the base-2 exponent of 'number'.
int     base2Exp    (float      number
                )
{
  unsigned int  u   = *(unsigned int*)&number;
  int       field   = (u & MANTISSA_MASK) | (EXPONENT_BIAS << EXPONENT_SHIFT);  // CHANGE THAT 0!
  return (field);  // CHANGE THAT 0!
}


//  PURPOSE:  To return the mantissa field of 'number'.  Turns on hidden bit
//  if 'number' is not denormalized.
unsigned int    mantissaField   (float      number
                )
{
  unsigned int  u   = *(unsigned int*)&number;
  unsigned int  field   = (u & MANTISSA_MASK) | (EXPONENT_BIAS << EXPONENT_SHIFT);  // CHANGE THAT 0!

  // YOUR CODE HERE

  return(field);
}


//  PURPOSE:  To return the float with exponent 'exponent' and mantissa-field
//      'mantissa'.
float       buildFloat  (int        exponent,
                 unsigned int   mantissa
                )
{
  unsigned int  exponentPattern;
  float     number;

  // YOUR CODE HERE to compute exponentPattern

  // YOUR CODE HERE to turn off the hidden bit in mantissa

  *((unsigned int*)&number) = 0;  // CHANGE THAT 0!
                                      // It should be an bitwise integer expression
                                      //  combining exponentPattern and mantissa
  return(number);
}


//  PURPOSE:  To return '+1.0' plus 'number' for non-negative 'number'.
//      Use integer operations only.
float       addOne      (float      number
                )
{

  int       exponent    = base2Exp(number);
  unsigned int  numberMantissa  = mantissaField(number);
  unsigned int  oneMantissa = MANTISSA_HIDDEN_BIT;

  // YOUR CODE HERE to handle number so small should return +1.0

  // YOUR CODE HERE to handle number so big should return number

  // YOUR CODE HERE to handle exponent < 0

  // YOUR CODE HERE to handle exponent > 0

  // Add mantissas (done)
  unsigned int  mantissa= numberMantissa + oneMantissa;

  // YOUR CODE HERE to handle when mantissa is too big

  // Build the resulting float (done)
  return(buildFloat(exponent,mantissa));
}


//  PURPOSE:  To run the add +1.0 program.  Ignores parameters.
//  Returns &EXIT_SUCCESS& to OS.
int     main        ()
{
  float     TEST_ARRAY[]    = { +0.0,
                    +FLT_MIN,
                    +1e-10,
                    +0.0625,
                    +0.5,
                    +0.75
                    +1.0,
                    +2.0,
                    +3.14159,
                    +7.5,
                    +1e+10,
                    +FLT_MAX
                  };
  const int TEST_ARRAY_LEN  = sizeof(TEST_ARRAY) / sizeof(float);
  int       i;
  int       j;
  int       EXPONENT_ARRAY[]= {2,2,
                   DENORMALIZED_POWER_OF_2,
                   DENORMALIZED_POWER_OF_2};
  int       MANTISSA_ARRAY[]= {0x800000,0xC00000,0x400000,0x600000};
  float     FLOAT_ARRAY[]   = {4.0,6.0,5.877471754e-39,8.816207631e-39};

  for  (i = 0;  i < 4;  i++)
  {
    float   f   = FLOAT_ARRAY[i];
    float   built   = buildFloat(EXPONENT_ARRAY[i],MANTISSA_ARRAY[i]);

    printf("%g == %g %s\n",f,built,( (f==built) ? "YAY!" : "Ruh-Roh!" ));
  }

  for  (i = 0;  i < TEST_ARRAY_LEN;  i++)
  {
    float   addend  = TEST_ARRAY[i];
    float   hardware= 1.0 + addend;
    float   student = addOne(addend);

    printf("1.0 + %11g = (hardware %11g) (you %11g) %s\n",
           addend,hardware,student,
       (hardware==student) ? "YAY!" : "Ruh-Roh!"
      );
  }

  return(EXIT_SUCCESS);
}





That's the code I have. I have tried to do the first two but I am not sure if they are correct because it does not output anything different. The output I should have is this:


4 == 4 YAY!
6 == 6 YAY!
5.87747e-39 == 5.87747e-39 YAY!
8.81621e-39 == 8.81621e-39 YAY!
1.0 +           0 = (hardware           1) (you           1) YAY!
1.0 + 1.17549e-38 = (hardware           1) (you           1) YAY!
1.0 +       1e-10 = (hardware           1) (you           1) YAY!
1.0 +      0.0625 = (hardware      1.0625) (you      1.0625) YAY!
1.0 +         0.5 = (hardware         1.5) (you         1.5) YAY!
1.0 +        1.75 = (hardware        2.75) (you        2.75) YAY!
1.0 +           2 = (hardware           3) (you           3) YAY!
1.0 +     3.14159 = (hardware     4.14159) (you     4.14159) YAY!
1.0 +         7.5 = (hardware         8.5) (you         8.5) YAY!
1.0 +       1e+10 = (hardware       1e+10) (you       1e+10) YAY!
1.0 + 3.40282e+38 = (hardware 3.40282e+38) (you 3.40282e+38) YAY!

However, after what I tried doing it still outputs the wrong output.

It outputs this:


4 == 0 Ruh-Roh!
6 == 0 Ruh-Roh!
5.87747e-39 == 0 Ruh-Roh!
8.81621e-39 == 0 Ruh-Roh!
1.0 +           0 = (hardware           1) (you           0) Ruh-Roh!
1.0 + 1.17549e-38 = (hardware           1) (you           0) Ruh-Roh!
1.0 +       1e-10 = (hardware           1) (you           0) Ruh-Roh!
1.0 +      0.0625 = (hardware      1.0625) (you           0) Ruh-Roh!
1.0 +         0.5 = (hardware         1.5) (you           0) Ruh-Roh!
1.0 +        1.75 = (hardware        2.75) (you           0) Ruh-Roh!
1.0 +           2 = (hardware           3) (you           0) Ruh-Roh!
1.0 +     3.14159 = (hardware     4.14159) (you           0) Ruh-Roh!
1.0 +         7.5 = (hardware         8.5) (you           0) Ruh-Roh!
1.0 +       1e+10 = (hardware       1e+10) (you           0) Ruh-Roh!
1.0 + 3.40282e+38 = (hardware 3.40282e+38) (you           0) Ruh-Roh!

I would really appreciate it if anyone can guide me through this. I have just started learning C and I am lost.

Thank you


Solution

  • I took a quick look at the code and the tasks you need to do. A few pointers: