提问者:小点点

我们如何才能清楚地知道C/C中的双精度或浮点精度?[关闭]


想要改进这个问题?通过编辑这篇文章添加细节并澄清问题。

假设我们有一个实数a,它具有无限精度。现在,我们在C/C中有浮动类型doubleflot,并希望使用这些类型表示a。假设“a_f”是a的变量名称。

我已经理解了这些值是如何表示的,它由以下三部分组成:符号、分数和指数。根据使用的类型,分配给分数和指数的位数不同,这决定了“精度”。

在这个意义上,精度是如何定义的?

这是a之间绝对差异的上界a_f(|a-a_f|),还是别的什么?

double的情况下,为什么“精度”以2^{-54}为界??

谢谢你。


共3个答案

匿名用户

浮点类型的精度通常定义为尾数中的位数,可以使用std::numeric_limits

尾数中的位数根据基数定义,使用std::numeric_limits

浮点类型的位数和基数都是实现定义的。我不知道任何实际实现支持2以外的浮点基数(但C标准不需要)。

如果基数是2std::numeric_limits

当将实值a存储在浮点变量中时,存储的实际变量(您所描述的a_f)是可以表示的最接近的近似值(假设不发生溢出等影响)。两者之间的差异(或差异的大小)不仅取决于尾数——它还取决于浮点指数——因此没有固定的上限。

实际上(用非常不准确的术语),一个值和它的浮点近似之间可能的差异与值的大小有关。浮点变量不代表最小和最大可表示值之间的一组均匀分布的值——这是使用尾数和指数表示的权衡,这是能够表示比相同大小的整数类型更大范围的值所必需的。

匿名用户

浮点数的问题是,它们越大或越小,就会变得越innacurate。例如:

double x1 = 10;
double x2 = 20;

std::cout << std::boolalpha << (x1 == x2);

正如预期的那样,打印false

但是,以下代码:

// the greatest number representable as double. #include <limits>
double x1 = std::numeric_limits<double>::max();
double x2 = x1 - 10;

std::cout << std::boolalpha << (x1 == x2);

出乎意料地打印出true,因为数字太大以至于您无法真正表示x1-10。它被四舍五入为x1

然后人们可能会问界限在哪里以及什么是界限。当我们看到不一致时,我们显然需要一些工具来检查它们。

std::之后的下一个:

std::nextAfter需要两个flotdoubles。第一个参数是我们的起点,第二个参数代表我们想要计算下一个可表示值的方向。例如,我们可以看到:

double x1 = 10;
double x2 = std::nextafter(x1, std::numeric_limits<double>::max());

std::cout << std::setprecision(std::numeric_limits<double>::digits) << x2;

x2略多于10。另一方面:

double x1 = std::numeric_limits<double>::max();
double x2 = std::nextafter(x1, std::numeric_limits<double>::lowest());

std::cout << std::setprecision(std::numeric_limits<double>::digits)
          << x1 << '\n' << x2;

我机器上的输出:

1.79769313486231570814527423731704356798070567525845e+308
1.7976931348623155085612432838450624023434343715745934e+308
                 ^ difference

这只是小数点后第16位。考虑到这个数字乘以10308,您可以看到为什么除以10绝对没有改变。

很难谈论具体的值。人们可能会估计double的精度为15位(点之前和之后的组合),这是一个不错的估计,但是,如果您想确定,请使用为该特定任务设计的方便工具。

匿名用户

例如,数字123456789可以表示为.12*10^9,也可以表示为.12345*10^9.1234567*10^9。这些都不是精确的表示,有些比其他更好。你选择哪一个取决于你有多少位作为分数。更多的位意味着更高的精度。用于表示分数的位数称为“精度”。