0

我正在使用 Visual C++ 2008 Express Edition,当我调试代码时:

double x = 0.2;

我在 x 0.200000000000000001 上的调试工具提示中看到

但:

typedef numeric_limits< double > double_limit; 
int a = double_limit::digits10

给我:a = 15

为什么调试器中的结果比正常的 c++ 精度长?这种奇怪的精度是基于什么?

我的 CPU 是 Intel Core 2 Duo T7100

4

3 回答 3

3

你需要阅读这篇文章:每个计算机科学家都应该知道的关于浮点运算的知识

于 2010-03-18T19:08:19.907 回答
1

您所看到的是由于实数(读取浮点数)无法在二进制计算机中以完美的精度和准确度表示。这是生活中的事实。相反,计算机会近似该值并以定义的格式将其存储在内存中。

对于大多数现代机器(包括运行 MSVC Express 的任何机器),这种格式是IEEE 754

长话短说,这就是 IEEE 754 中实数的存储方式:有一个符号位、8 个指数位和 23 个小数位(对于float数据类型——doubles相应地使用更多位,但格式相同)。因此,您永远无法达到完美的精度和准确性。幸运的是,您几乎可以为包括关键金融系统和科学系统在内的任何应用程序实现足够的准确性和精确度。

您无需了解有关 IEEE754 的所有信息即可在代码中使用浮点数。但是有几点你必须知道:

1)由于浮点计算和存储中固有的舍入误差,您永远无法比较 2 个浮点值是否相等。相反,您必须执行以下操作:

double d = 0.2;
double compare = 0.000000001;

double d2 = something;

if( (d - d2 < compare) && (d2 - d < compare) )
{
  // numbers are equal
}

2) 舍入误差复合。对浮点值执行操作的次数越多,精度损失就越大。

3)您不能添加两个幅度差异很大的浮点数。例如,您不能添加 1.5x10^30 和 1.5x10^-30 并期望 60 位精度。

于 2010-03-18T19:22:14.940 回答
0

双字面值给你的确切值0.2是 0.200000000000000011102230246251565404236316680908203125。

大多数输出​​双精度数的函数在一定数量的十进制数字后被削减,这就是为什么你会0.2产生实际产生 0.2的错觉

这是我获得确切值的方法:

public static void main(String[] args)
{
    System.out.println(new java.math.BigDecimal(0.2));
}
于 2010-03-18T19:33:26.533 回答