如何在c++中获得长双精度的有效位长度?

  • 本文关键字:双精度 有效位 c++ c++
  • 更新时间 :
  • 英文 :


通过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;
}

最新更新