我使用一个系数进行比较(作为地图键),该系数总是大于1,通常要大得多。使用反向版本(1 / coeff)更精确吗?系数定义了一些比例,并通过将一个双数除以另一个来获得,因此可以通过两种不同的方式轻松执行。
在程序设计中没有太大的区别,但是我已经在某处读到了双数字的实现增加了比较精度"不到一个双重值比其他值小(例如0 关于非均匀数密度的一些相关问题:
How many bits of precision for a double between -1.0 and 1.0?
答案 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都相同,但是它们不相同