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我怀疑可以通过以下规则:
用下面的表达式模糊地说:
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.背景:我试图解决两个问题:
简而言之,没有。如果std::numeric_limits<T>::is_iec559,那么您T或多或少知道 的格式:您仍然必须确定字节顺序。对于其他任何事情,所有赌注都没有了。(我知道仍在使用的其他格式甚至不是基数 2:例如,IBM 大型机使用基数 16。)IEC 浮点的“标准”排列在高位上有符号,然后是指数,以及低位上的尾数;如果您可以成功地将其视为
uint64_t,例如(通过memcpy,reinterpret_cast或
union—`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.