这是否有区别:
average = (x1+x2)/2;
deviation1 = x1 -average;
deviation2 = x2 -average;
variance = deviation1*deviation1 + deviation2*deviation2;
和此:
average2 = (x1+x2);
deviation1 = 2*x1 -average2;
deviation2 = 2*x2 -average2;
variance = (deviation1*deviation1 + deviation2*deviation2) / 4;
请注意,在第二个版本中,我试图尽可能延迟分割。第二个版本[延迟划分]是否会提高准确性?
上面的代码段仅作为示例,我不是要尝试优化此特定代码段。
顺便说一下,我问的是一般的划分,不只是2或2的幂,因为它们减少到IEEE 754表示的简单移位。我将除法除以2,只是为了用一个非常简单的例子说明问题。答案 0 :(得分:3)
没有什么可以从中获得的。您只是在改变比例,但在计算中没有得到任何更重要的数字。
Wikipedia article on variance以高效的方式解释了计算方差的一些选项。
答案 1 :(得分:2)
由于IEEE754(可能可能你正在使用的内容),你无法获得精确度,因为无论你工作的规模如何,你都能获得相同的精度(位数)。例如3.14159 x 10 7 将精确到3.14159 x 10 10 。
唯一的可能的优势(前者)是在设置偏差时可以避免溢出。但是,只要值本身小于最大值的一半,那就不会有问题了。
答案 2 :(得分:1)
我必须同意David Heffernan,它不会给你更高的精确度。
原因是如何存储浮点值。您有一些代表有效数字的位和一些代表指数的位(例如3.1714x10-12)。无论你的数字有多大,有效数字的位总是相同的 - 这意味着最终结果不会是真正不同的数字。
更糟糕的是 - 如果你有非常大的数字,推迟分裂可能会让你溢出。
如果你真的需要更高的精度,那么有很多库可以提供更高精度的大数字或数字。
答案 3 :(得分:1)
回答问题的最佳方法是运行测试(随机分布和基于范围的?)并查看结果数字在二进制表示中是否完全不同。
请注意,如果执行此操作,您将遇到的一个问题是,由于您的代码平均值,您的函数将无法用于值> MAX_INT/2
。
avg = (x1+x2)/2 # clobbers numbers > MAX_INT/2
avg = 0.5*x1 + 0.5*x2 # no clobbering
除非您正在编写语言级库,否则这几乎肯定不是问题。如果你的大部分数字很小,那可能无关紧要?事实上,它可能不值得考虑,因为方差值将超过MAX_INT
,因为它是一个平方数量;我想你可能希望使用标准偏差,但没有人这样做。
这里我在python中进行了一些实验(我认为它可以支持IEEE,因为它可能会将数学委托给C库......):
>>> def compare(numer, denom):
... assert ((numer/denom)*2).hex()==((2*numer)/denom).hex()
>>> [compare(a,b) for a,b in product(range(1,100),range(1,100))]
没问题,我认为因为除以2的除法和乘法在二进制中可以很好地表示。但是尝试乘法和除法3:
>>> def compare(numer, denom):
... assert ((numer/denom)*3).hex()==((3*numer)/denom).hex(), '...'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <listcomp>
File "<stdin>", line 2, in compare
AssertionError: 0x1.3333333333334p-1!=0x1.3333333333333p-1
这可能很重要吗?也许如果您使用非常小的数字(在这种情况下,您可能希望使用对数算法)。但是,如果你正在处理大数(概率不常见)并且你推迟除法,你会提到风险溢出,但更糟糕的是,由于难以阅读的代码而导致的风险错误。 / p>