如何确定以浮点数、双精度位数为单位的有效宽度:是否有标准定义?

How can the significand width in bits of float, double be determined: Is there a standard definition?

本文关键字:是否 定义 标准 有效 浮点数 确定以 双精度 为单位      更新时间:2023-10-16

是否有标准方法来确定双精度的有效数的宽度,以 C 或 C++ 为单位? 我知道 IEEE-754 格式的双精度存储 53 位的有效位数,但我想避免在我的代码中使用"魔术"数字。

在 Linux 上,该文件usr/include/ieee754.h存在,但它使用结构中的位字段描述格式,我无法确定(在编译时)的大小。

仅 Linux 的解决方案是可以接受的。

使用FLT_MANT_DIGDBL_MANT_DIG,在<float.h>中定义:

#include <float.h>
#include <stdio.h>

#if FLT_RADIX != 2
#error "Floating-point base is not two."
#endif

int main(void)
{
printf("There are %d bits in the significand of a float.n",
FLT_MANT_DIG);
printf("There are %d bits in the significand of a double.n",
DBL_MANT_DIG);
}

有没有确定替身尾数的标准方法?

你愿意接受一个特定于Linux的解决方案,但你声称glibc的ieee754.h标头不能满足你的需求,所以我的结论是,你试图解决的问题不是提取或传达位本身,因为该标头的union ieee_double会为你提供一种方法来做到这一点。

我把"尾数"读成与"尾数"不同的东西,所以我得出结论,DBL_MANT_DIGfloat.h也不是你要找的。

我能想到的唯一另一件事可能是根据标准浮点模型的有效数(尾数)的值

v= (符号) *有效数*数指数

自 C99 以来的 C 语言标准中的frexp()函数用于此目的。1它将double分为指数(2)和有效数,表示为double。 对于有限的非零输入,结果的绝对值在半开区间 [0.5, 1] 内。

示例

#include <math.h>
#include <stdio.h>
void print_parts(double d) {
int exp;
double significand = frexp(d, &exp);
printf("%e = %f * 2^%dn", d, significand, exp);
}

示例输出

7.256300e+16 = 0.503507 * 2^57
1.200000e-03 = 0.614400 * 2^-9-0.000000e
+00 = -0.000000 * 2^0

请注意,尽管示例函数没有打印足够的十进制数字来准确传达有效数,但frexp()本身是精确的,不受任何舍入误差的影响。


1从技术上讲,frexp()达到目的,前提是FLT_RADIX扩展到 2。 在任何情况下,它都是明确定义的,但是如果您的double表示使用不同的基数,那么frexp()的结果虽然定义良好,但可能不是您要查找的。

在C++中,您可以使用std::numeric_limits<double>::digitsstd::numeric_limits<float>::digits

#include <limits>
#include <iostream>
int main()
{
std::cout << std::numeric_limits<float>::digits << "n";
std::cout << std::numeric_limits<double>::digits << "n";
}

指纹

24
53

分别。