Reputation: 31
As cppreference says "In IEEE 754, the most common binary representation of floating-point numbers, the positive infinity is the value with all bits of the exponent set and all bits of the fraction cleared.". I tried this code snippet, but I don't see exponent bits set. Am I wrong somewhere?
#include <iostream>
#include <limits>
#include <bitset>
#include <math.h>
using namespace std;
int main() {
float a = 0b00000000000000000000000000000000;
double b = std::numeric_limits<double>::infinity();
bitset<64> x(b);
cout<<x<<endl;
return 0;
}
It prints 0000000000000000000000000000000000000000000000000000000000000000 on console.
Upvotes: 3
Views: 1726
Reputation: 20080
0000000000000000000000000000000000000000000000000000000000000000
Really?
Mine prints
#include <cmath>
#include <iostream>
#include <limits>
#include <bitset>
const char NL = '\n';
int main() {
typedef union {
double d;
uint64_t u;
} du;
du b;
b.d = std::numeric_limits<double>::infinity();
std::bitset<64> x(b.d);
std::cout << x << " " << b.u << NL;
std::cout << std::bitset<64>(b.u) << NL;
return 0;
}
1000000000000000000000000000000000000000000000000000000000000000 9218868437227405312
and last line prints
0111111111110000000000000000000000000000000000000000000000000000
Yes, UB, I know, I know
Upvotes: 1
Reputation: 238331
std::bitset
doesn't have a constructor accepting a double
. When you pass double
, you instead invoke the constructor that accepts unsigned long long
and the double
is first implicitly converted to unsigned long long
.
Problem is, unsigned long long
cannot represent infinity, and the behaviour of the program is consequently undefined. Standard says:
[conv.fpint]
A prvalue of a floating-point type can be converted to a prvalue of an integer type. The conversion truncates; that is, the fractional part is discarded. The behavior is undefined if the truncated value cannot be represented in the destination type.
To see the bits, you can first "bitcast" the floating point to an integer type, and then pass that integer to bitset:
auto int_b = std::bit_cast<std::uint64_t>(b);
std::bitset<64> x(int_b);
Upvotes: 5
Reputation: 14423
The line
bitset<64> x(b);
implicitly converts b
to an unsigned long long
(or unsigned long
prior to C++11) to invoke the bitset(unsigned long long)
constructor of std::bitset
.
Note that when converting between a floating point type and an integral type, the behavior is undefined if value cannot be represented in the destination type (N4659 7.10/1). So, creating a bitset in this way could lead to anything being printed.
Upvotes: 0