Search code examples
c++floating-pointmemcpystd-bitset

Float to 4 uint8_t and display


I read from float in Wikipedia and i tried print his bits. i used std::bitset and this return other bits different from what I expected(i know because i used the same number of the example in the link), then i used memcpy() and copy the memory of float to 4 parts of 1 byte each and print, this method worked but i have 4 questions.

1) Why using bitset in a float, this print only the integer part?
2) Why bitset working only with the array and not with the float?
3) memcpy() worked in correct order?

The last question is because 0.15625f == 0b00111110001000000000000000000000.
Then i think that the correct order is:

bb[0] == 0b00111110;
bb[1] == 0b00100000;
bb[2] == 0b00000000;
bb[3] == 0b00000000;

But the order returned is inverse.

4) Why happend this ?

My code:

#include <cstring>
#include <iostream>
#include <bitset>

int main(int argc,char** argv){

        float f = 0.15625f;

        std::cout << std::bitset<32>(f) << std::endl;
        //print: 00000000000000000000000000000000
        //This print only integer part of the float. I tried with 5.2341 and others

        uint8_t bb[4];
        memcpy(bb, &f, 4);

        std::cout << std::bitset<8>(bb[0]) << std::endl;
        //print: 00000000
        std::cout << std::bitset<8>(bb[1]) << std::endl;
        //print: 00000000
        std::cout << std::bitset<8>(bb[2]) << std::endl;
        //print: 00100000
        std::cout << std::bitset<8>(bb[3]) << std::endl;
        //print: 00111110

        return 0;
}

Solution

    1. To construct std::bitset from a float, one of std::bitset construtors is used. The one that is relevant here is

      constexpr bitset(unsigned long long val) noexcept;
      

      Before this constructor is called, float is converted into unsigned long long, and its decimal part is truncated. std::bitset has no constructors that take floating-point values.

    2. The bytes order of floating-point numbers is affected by machine endianness. On a little-endian machine bytes are stored in the reverse order. If your machine uses the same endianness for floating-point numbers and for integers, you can simply write

      float f = 0.15625f;
      std::uint32_t b;
      std::memcpy(&b, &f, 4);
      std::cout << std::bitset<32>(b) << std::endl; 
      // Output: 00111110001000000000000000000000
      

      to get bytes in the correct order automatically.