是否有符合C ++标准的方法来确定“浮动”,“双重”和“长”双重结构的结构。在编译时(或运行时,作为替代)?
如果我假设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
包含&#34;整数位&#34;,无论格式是否实际明确代表它,所以我不知道如何以编程方式检测并调整此格式。std::numeric_limits< T >::max_exponent
总是2^(num_exponent_bits)/2
。背景:我试图轻易克服两个问题:
答案 0 :(得分:4)
简而言之,没有。如果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;
表示`float:
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;
关于long double
,情况更糟,因为不同
编译器对它的处理方式不同,即使是在同一台机器上。
名义上,它是十个字节,但出于对齐原因,它可能在
事实上是12或16.或者只是double
的同义词。 如果那就是
超过10个字节,我想你可以指望它被打包
进入前10个字节,以便&myLongDouble
给出
10字节值的地址。但总的来说,我会避免
long double
。
答案 1 :(得分:1)
我想说唯一可移植的方法是将数字存储为字符串。这不依赖于“解释位模式”
即使您知道有多少位,也不意味着它具有相同的表示 - 指数从零开始或有偏差。尾数前面有一个看不见的1吗?这同样适用于该号码的所有其他部分。 BCD编码或“十六进制”浮点数变得更糟 - 这些在一些架构中可用......
如果您担心结构(类,数组等)中未初始化的位,则使用memset将整个结构设置为零[或其他一些已知值]。
答案 2 :(得分:0)
对于子孙后代,这就是我最终要做的事情。
为了生成并测试我的IEEE-754信令-NAN值,我将此模式用于'float'和'double'。
#include <cstdint> // uint32_t, uint64_t
#include <limits> // numeric_limits
union IEEE754_Float_Union
{
float value;
uint32_t bits;
};
float generate_IEEE754_float()
{
IEEE754_Float_Union u = { -std::numeric_limits< float >::signaling_NaN() };
size_t const num_significand_bits_to_set = std::numeric_limits< float >::digits
- 1 // implicit "integer-bit"
- 1; // the "signaling-bit"
u.bits |= ( static_cast< uint32_t >( 1 ) << num_significand_bits_to_set ) - 1;
return u.value;
}
bool test_IEEE754_float( float const& a_r_val )
{
IEEE754_Float_Union const u = { a_r_val };
IEEE754_Float_Union const expected_u = { generate_IEEE754_float() };
return u.bits == expected_u.bits;
}
对于'long double',我使用'double'函数进行强制转换。具体来说,我生成'double'值并在返回之前将其转换为'long double',然后通过转换为'double'然后测试该值来测试'long double'。我的想法是,虽然'long double'格式可以变化,但是将'double'转换为'long double',然后将其转换回'double'应该是一致的(即不要丢失任何信息。)< / p>