如何在 C++ 中以浮点/双精度值表示无穷大?

时间:2021-02-04 16:02:14

标签: c++ ieee-754 infinite

正如 cppreference 所说的“在 IEEE 754 中,浮点数的最常见二进制表示形式,正无穷大是指数的所有位都被设置并且分数的所有位都被清除的值。”。我试过这个代码片段,但我没有看到指数位设置。我是不是哪里错了?

#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;
}

它在控制台上打印 0000000000000000000000000000000000000000000000000000000000000000。

3 个答案:

答案 0 :(得分:4)

std::bitset 没有接受 double 的构造函数。当您传递 double 时,您改为调用接受 unsigned long long 的构造函数,并且 double 首先隐式转换为 unsigned long long

问题是,unsigned long long 不能表示无穷大,因此程序的行为是未定义的。标准说:

<块引用>

[conv.fpint]

浮点类型的纯右值可以转换为整数类型的纯右值。 转换截断;也就是说,小数部分被丢弃。 如果截断的值无法在目标类型中表示,则行为未定义。


要查看位,您可以先将浮点“bitcast”为整数类型,然后将该整数传递给 bitset:

auto int_b = std::bit_cast<std::uint64_t>(b);
std::bitset<64> x(int_b);

答案 1 :(得分:1)

<块引用>

0000000000000000000000000000000000000000000000000000000000000

真的吗?

我的指纹

#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;
}

1000000000000000000000000000000000000000000000000000000000000 9218868437227405312

和最后一行打印

01111111111100000000000000000000000000000000000000000000000000

是的,UB,我知道,我知道

答案 2 :(得分:0)

线

bitset<64> x(b);

b 隐式转换为 unsigned long long(或 C++11 之前的 unsigned long)以调用 std::bitsetbitset(unsigned long long) 构造函数。

请注意,在浮点类型和整数类型之间进行转换时,如果值无法在目标类型中表示,则行为未定义 (N4659 7.10/1)。因此,以这种方式创建位集可能会导致任何内容被打印。