通过std::numeric_limits
,我们可以得到long double
的一些信息,如最大/最小值。通过sizeof(long double)
可以得到内存的使用情况
但是long double
的有效字节/位在c++标准中没有规定,可能是80/96/128或其他,那么是否有编译时的方法来获得有效的位长度?
可移植的方法更好。
void dump(auto x)
{
auto vss = bit_cast<bitset<sizeof(x) * 8>>(x);
cout << vss.to_string().substr(0, 48) << ' ' << vss.to_string().substr(48) << endl;
}
int main(int argc, char const *argv[])
{
long double x = 0;
dump(x);
dump(-x);
return 0;
}
在x86-64上,您将看到只有第79位被翻转。因此,所有128位中只有80位是有效的。
#include <bit>
#include <cstddef>
constinit size_t valid_bits = []
{
long double zero{};
struct long_double_bytes
{
unsigned char b[sizeof(long double)];
};
long_double_bytes x = std::bit_cast<long_double_bytes>(zero);
long_double_bytes y = std::bit_cast<long_double_bytes>(-zero);
for (size_t i = 0; i < sizeof(long double); i++)
{
x.b[i] ^= y.b[i];
}
size_t r = 0, i;
for (i = 0; i < sizeof(long double) && !x.b[i]; i++)
{
r += 8;
}
for (size_t j = 0; j < 8 && !((x.b[i] >> j) & 1); j++)
{
r++;
}
return r + 1;
}();
编译时解决方案。
仅仅计算零件位还不够吗?
#include <iostream>
#include <cfloat>
static unsigned int ilog2(unsigned int val) {
if (val == 0) return UINT_MAX;
if (val == 1) return 0;
unsigned int ret = 0;
while (val > 1) {
val >>= 1;
ret++;
}
return ret;
}
int main() {
unsigned int bitsinLDBL = LDBL_MANT_DIG; // mantissa
bitsinLDBL += ilog2(LDBL_MAX_EXP); // exponent
bitsinLDBL += 1u; // sign bit
std::cout << bitsinLDBL << " " << bitsinLDBL/CHAR_BIT << 'n';
return 0;
}