0

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;
}
Pipe Soto
  • 320
  • 2
  • 9
  • 1
    Endianness? Looks like you're running on a little endian computer. https://en.wikipedia.org/wiki/Endianness – Abhyudaya Sharma Nov 27 '19 at 06:43
  • 2
    `std::bitset<32>(f)` will first convert `f` into `unsigned long long`. – Evg Nov 27 '19 at 06:45
  • Constructor std::bitset( unsigned long val ). You can use ` uint32_t f2 = *((uint32_t*)(&f)); std::cout << std::bitset<32>(f2) << std::endl;` – shang12 Nov 27 '19 at 07:00
  • 2
    @shang12, `((uint32_t)(&f))` is undefined behavior. Use `memcpy`. – Evg Nov 27 '19 at 07:04
  • Character asterisk(*) doesn't display in my comment. I want to write uint32_t f2 = * ((uint32_t * )(&f)) – shang12 Nov 27 '19 at 07:08
  • @shang12, `*` is not the problem. See [this question](https://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule). – Evg Nov 27 '19 at 07:10
  • @Evg, thank for your information. With built-in data type, this is not the problem. – shang12 Nov 27 '19 at 07:22
  • @shang12, if you want your code to conform to the C++ standard, it **is** a problem. If you don't, do it. – Evg Nov 27 '19 at 07:27
  • @shang12 Wrap any code in the comments (and any inline code in questions/answers) in \` symbols. So \`asd\` will turn into `asd`. And listen to Evg, the correct way to do it is `memcpy`. Compilers understand what you are doing and will optimize it away. – Max Langhof Nov 27 '19 at 08:57

1 Answers1

3
  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.

Evg
  • 25,259
  • 5
  • 41
  • 83