C ++中的小型和大型双精度值:哪个更精确?

时间:2014-10-21 07:14:05

标签: c++ double

我使用一个系数进行比较(作为地图键),该系数总是大于1,通常要大得多。使用反向版本(1 / coeff)更精确吗?系数定义了一些比例,并通过将一个双数除以另一个来获得,因此可以通过两种不同的方式轻松执行。

在程序设计中没有太大的区别,但是我已经在某处读到了双数字的实现增加了比较精度"不到一个双重值比其他值小(例如0


关于非均匀数密度的一些相关问题: How many bits of precision for a double between -1.0 and 1.0?

2 个答案:

答案 0 :(得分:2)

假设您的数字不是整数,那么它不会改善或恶化实际的"准确性"要做1 / x的数字 - 它会变得更糟,因为你正在做另一个数学运算。所以我会单凭这个原因避免它。

所有浮点数都有有限的位数来表示尾数。 "有多精确"没有任何区别。值是1 / x还是x。在浮点数的二进制形式中,就像十进制形式一样,我们不能将1/3表示为十进制数(这里不是3的无限供应),因此0.1变为0.0999999999999999999999999。 ...如果你试图以二进制形式表达它。如果数字是10.1,8.1或100001.1,以及0.2,0.4,0.3,0.7,0.8,0.9 [以及包含该数字的任何其他数字],这并不重要。另一方面,0.5,0.25,0.125完美地#34;很好"二进制。

你真的不能制造一个浮点值"更好"通过做数学就可以了。它只会变得更糟糕" (但它确实(1/2 52 )更糟糕,所以对大多数情况来说可能不是很重要。)

澄清:

让我们说我们的值为100(以浮点精确表示,因为它是一个整数,并且所有小于2 mantissa_bits 的整数都以完全精度存储且没有错误)。 1/100是0.01。如果我们做"十进制到二进制"对此: 首先乘以2,直到我们得到一个数字> = 1:

0.01 * 2 = 0.02 
0.02 * 2 = 0.04
0.04 * 2 = 0.08
0.08 * 2 = 0.16
0.16 * 2 = 0.32  // We're getting there 
0.32 * 2 = 0.64
0.64 * 2 = 1.28  // Exponent = -(steps we needed) to get here = -7
                 // Mantissa (M) so far = 1

现在我们有一点。减1并重复乘以2

0.28 * 2 = 0.56 // M = 1.0    0.56 * 2 = 1.12 // M = 1.01 - 减1    0.12 * 2 = 0.24 // M = 1.010    0.24 * 2 = 0.48 // M = 1.0100    0.48 * 2 = 0.96 // M = 1.01000    0.96 * 2 = 1.92 // M = 1.010000    0.92 * 2 = 1.84 // M = 1.0100001    0.84 * 2 = 1.76 // M = 1.01000011    0.76 * 2 = 1.52 // M = 1.010000111    0.52 * 2 = 1.04 // M = 1.0100001111    0.04 * 2 = 0.08 // M = 1.01000011110
   0.08 * 2 = 0.16 // M = 1.010000111100

请记住,我们之前已经看到了0.04,0.08的数字 - 这将永远持续下去。

所以,我们从一个准确的数字开始,这变得不准确。如果你从一个不准确的数字开始,你就不会得到一个准确的数字(处理器的浮点部分它没有意识到0.00999999999999999999999999999999999999999实际上是0.01 - 即使它向上/向下舍入实际结果)。

Edit2:大+小数的加/减。

现在,在一个很大的数字中添加一个非常小的数字,这是另一回事。这一切都取决于所涉及的数字的确切范围。在进行加法或减法时,数字会被标准化(就像你在纸上做同样的事情一样)。所以我们得到:

500000 + 0.000000025

 500000.000000000
+     0.000000025
 ----------------
 500000.000000025

现在,如果在我们乘以2之前小数不适合直到它们具有相同的指数,则问题就出现了。在这种情况下,0.000000025约为2 -25 ,500000为~2 19 - 19 + 25 = 44,因此在53位范围内,但0.000000025值可能为略微圆润[我还没有完成转换,看看它是否是"精确"或者"不准确"浮点数]。

换句话说,在这种情况下,它有效。当然,它会对整体价值产生非常小的影响,但我希望这是意图,或者您已经使用了更大的数字来添加。

答案 1 :(得分:0)

为了在映射中保持键值对,我建议在十进制之后具有n位数的固定精度(在十进制之后向上舍入到n位数)然后具有字符串或整数(将double值乘以10 ^ n并且以整体部分为关键,以避免混淆和惊喜。在浮点运算中,1.00000000001和0.9999999999999都相同,但是它们不相同