C++移动浮点位表示?

Cha*_*cox 8 c++ floating-point portability ieee-754 bit-representation

是否有符合C++标准的方法来确定编译时(或运行时,作为替代)的'float','double'和'long double'的结构?

如果我假设,std::numeric_limits< T >::is_iec559 == true并且std::numeric_limits< T >::radix == 2我怀疑可以通过以下规则:

  • 第一个X位是有效数.
  • 下一个Y位是指数.
  • 最后1位是符号位.

用下面的表达式模糊地说:

  • size_t num_significand_bits = std::numeric_limits< T >::digits;
  • size_t num_exponent_bits = log2( 2 * std::numeric_limits< T >::max_exponent );
  • size_t num_sign_bits = 1u;

除了我知道

  • std::numeric_limits< T >::digits 包括"整数位",无论格式是否实际明确表示它,所以我不知道如何以编程方式检测和调整.
  • 我猜std::numeric_limits< T >::max_exponent是永远的2^(num_exponent_bits)/2.

背景:我试图解决两个问题:

  • 设置/获取有效位中的哪些位.
  • 确定'long double'结尾的位置,所以我知道不要读取具有未初始化内存的隐式填充位.

Jam*_*nze 5

简而言之,没有。如果std::numeric_limits<T>::is_iec559,那么您T或多或少知道 的格式:您仍然必须确定字节顺序。对于其他任何事情,所有赌注都没有了。(我知道仍在使用的其他格式甚至不是基数 2:例如,IBM 大型机使用基数 16。)IEC 浮点的“标准”排列在高位上有符号,然后是指数,以及低位上的尾数;如果您可以成功地将其视为 uint64_t,例如(通过memcpyreinterpret_castunion—`memcpy 保证可以工作,但效率低于其他两个),则:

对于double

uint64_t tmp;
memcpy( &tmp, &theDouble, sizeof( double ) );
bool isNeg = (tmp & 0x8000000000000000) != 0;
int  exp   = (int)( (tmp & 0x7FF0000000000000) >> 52 ) - 1022 - 53;
long mant  = (tmp & 0x000FFFFFFFFFFFFF) | 0x0010000000000000;
Run Code Online (Sandbox Code Playgroud)

对于`浮动:

uint32_t tmp;
memcpy( &tmp, &theFloat, sizeof( float ) );
bool isNeg = (tmp & 0x80000000) != 0;
int  exp   = (int)( (tmp & 0x7F800000) >> 23 ) - 126 - 24 );
long mant  = (tmp & 0x007FFFFF) | 0x00800000;
Run Code Online (Sandbox Code Playgroud)

关于long double,情况更糟,因为不同的编译器对它的处理方式不同,即使在同一台机器上也是如此。名义上,它是 10 个字节,但出于对齐的原因,它实际上可能是 12 或 16。或者只是double. 如果它超过 10 个字节,我你可以指望它被打包到前 10 个字节中,这样就&myLongDouble给出了 10 个字节值的地址。但一般来说,我会避免 long double.