C++float assigned to unsigned long y

I have to write separate C++ expression for:

1) extract the 8-bit exponent field to the low order bits of y, and subtract the 127 bias.
2) isolate the mantissa field in the lower order bits of y, and insert the implicit leading 1.

I am not expecting anyone to provide me with the answers, I only want some tips on how to go about understanding how to do this.

Dani AI

Generated

A few focused tips to finish the two expressions requested by and to complement 's suggestions.

Use a safe bit-copy to get the 32-bit pattern of the float into an unsigned 32-bit integer (type-punning via reinterpret_cast or union can be non-portable under the C++ standard). std::bit_cast (C++20) or std::memcpy are the portable options (std::bit_cast, std::memcpy).

Example extraction logic (portable):

uint32_t bits = float_bits(f);    // use bit_cast or memcpy to implement float_bits
uint32_t E    = (bits >> 23) & 0xFFu;    // raw 8-bit exponent
uint32_t M    = bits & 0x7FFFFFu;        // raw 23-bit fraction

int exponent;
if (E == 0) {
    exponent = 1 - 127;        // subnormal numbers: no implicit 1, exponent = -126
} else if (E == 255) {
    // special: infinity / NaN
} else {
    exponent = int(E) - 127;   // normalized numbers
    M |= 0x800000u;            // insert implicit leading 1 (24-bit significand)
}

Notes and gotchas:

  • Use uint32_t for bit ops; unsigned long may be 64-bit on some platforms and will break masks/shifts. Convert to unsigned long only after extraction if needed.
  • Do not blindly subtract 127 for E==0 (subnormals) or treat E==255 as a normal exponent — those are special cases.
  • The implicit leading 1 is only present for normalized values (E != 0). Add it by OR-ing 1u << 23 (0x800000).
  • Endianness does not affect bitwise masks/shifts once the bits are copied into a 32-bit integer on the same host, but watch for byte-order when exchanging raw bytes across systems.

These steps give the exact expressions needed: (bits >> 23) & 0xFF then subtract bias (with the subnormal/special-case adjustment), and bits & 0x7FFFFF then | 0x800000 when appropriate.

Recommended Answers

All 2 Replies

Reference: http://en.wikipedia.org/wiki/Single-precision_floating-point_format

#include <iostream>
// Needed for the hex, showbase, setfill and setw
#include <iomanip>
using namespace std;
int main(){
 // Set the floating point number
 float floatVal(-1);
 // Want the integer form of what the float looks like, not the integer
 // part of the float.
 unsigned int intValOfFloat(*reinterpret_cast<unsigned int*>(&floatVal));
 // Debug
 cout << showbase << setfill('0') << setw(8) << hex << intValOfFloat << endl;

 //
 // Now that the floating point number is an integer, extract the bits 
 // you want based on the picture below 
 //     ---------------------------------------------------------------------
 //    | s | e e e e e e e e | m m m m m m m m m m m m m m m m m m m m m m m |
 //     ---------------------------------------------------------------------
 // s = sign bit
 // e = exponent bits
 // m = mantissa bits

 // The output from the cout above is 0xbf800000.  
 // Does that make sense given that the floating point number was -1?
 // Try another number that is a power to 2 to make sure you understand.

 return 0;
}
Use a union, it's cleaner.
#include <iostream>
// Needed for the hex, showbase, setfill and setw
#include <iomanip>
using namespace std;
int main(){
  // ----------------------------------------------
  // I like this better.  It's cleaner no pointers.
  union {
    float        floatVal;
    unsigned int intVal;
  } x;

  x.floatVal = -1;
  // Want the integer form of what the float looks like, not the integer
  // part of the float.
  // Debug
  cout << showbase << setfill('0') << setw(8) << hex << x.intVal << endl;

  //
  // Now that the floating point number is an integer, extract the bits 
  // you want based on the picture below 
  //     ---------------------------------------------------------------------
  //    | s | e e e e e e e e | m m m m m m m m m m m m m m m m m m m m m m m |
  //     ---------------------------------------------------------------------
  // s = sign bit
  // e = exponent bits
  // m = mantissa bits

  // The output from the cout above is 0xbf800000.  
  // Does that make sense given that the floating point number was -1?
  // Try another number that is a power to 2 to make sure you understand.

  return 0;
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.