这有什么区别吗:
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,只是为了用一个非常简单的例子来说明这个问题。
发布于 2011-06-26 15:27:43
这不会带来任何好处。你只是改变了比例,但在你的计算中不会得到更多有意义的数字。
Wikipedia article on variance在高层次上以健壮的方式解释了计算方差的一些选项。
发布于 2011-06-26 15:44:03
我不得不同意大卫·赫弗南的观点,它不会给你更高的精确度。
原因在于浮点值的存储方式。有些位表示有效数字,有些位表示指数(例如3.1714x10-12)。无论你的数字有多大,有效数字的位数总是相同的--这意味着最终的结果不会真的不同。
更糟糕的是-如果你有非常大的数字,延迟除法可能会导致溢出。
如果你真的需要更高的精度,有很多库允许更大的数字或更高精度的数字。
发布于 2011-06-26 16:01:03
回答问题的最好方法是运行测试(包括随机分布的测试和基于范围的测试?)并查看所得到的数字在二进制表示中是否完全不同。
请注意,如果这样做,您将遇到的一个问题是,由于编码平均的方式,您的函数将不适用于值> MAX_INT/2。
avg = (x1+x2)/2 # clobbers numbers > MAX_INT/2
avg = 0.5*x1 + 0.5*x2 # no clobbering不过,这几乎肯定不是问题,除非您正在编写语言级别的库。如果你的大多数数字都很小,那可能根本无关紧要?事实上,它可能不值得考虑,因为方差的值将超过MAX_INT,因为它本质上是一个平方量;我想说你可能希望使用标准差,但没有人这样做。
在这里,我用python做了一些实验(我认为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和乘以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这可能很重要吗?也许如果您正在处理非常小的数字(在这种情况下,您可能希望使用log算法)。但是,如果您正在处理大数字(概率上不常见),并且延迟除法,您将会像我前面提到的那样发生风险溢出,但更糟糕的是,由于难以阅读的代码,可能会出现风险错误。
https://stackoverflow.com/questions/6482660
复制相似问题