我想计算perl中每行数字的方差.我写过这个子程序:
################################################################ # variance # # # A subroutine to compute the variance of an array # division by n-1 i s used # sub var{ my ($data) = @_; if (@$data ==1) { return 0; } my $mean = mean ($data); my $sqtotal = 0; foreach (@$data) { $sqtotal += ($_ - $mean) ** 2 } my $var = $sqtotal / (scalar @$data - 1); return $var; }
如果我给它这个数组有58个相同数字的元素
[0.98,0.98,0.98]
计算给了我1.25421964097639e-30.
我也尝试使用Statistics :: Descriptive模块(http://metacpan.org/pod/Statistics::Descriptive),它给了我2.11916254524942e-15.
我也试过这个网站(http://www.alcula.com/calculators/statistics/variance/),结果是2.2438191655582E-15.
为什么结果不一样……
我本可以刚刚使用该模块,但对我的文件来说,它的内存密集程度非常高,基本上由数百万行58个数字组成.我不确定为什么它消耗了这么多内存.
有人能告诉我为什么我的计算给出了与模块不同的数字,以及如何使模块以更少的内存工作?内存密集的东西只是该模块的固有缺点.几个帖子似乎暗示了这一点.
谢谢!
解决方法
常数序列的方差为零,因此您的计算或多或少都是正确的,并且或多或少都相同.
您得到的结果略有不同,因为您使用有限精度浮点数执行许多操作.我们来看看这段代码:
$z = 0; $z += 0.98 for 1..58; $mean = $z / 58; printf "%.20f",$mean;
使用此代码,我们取数字0.98的58个实例的总和,然后将总和除以58.有意义的是,此代码将打印出0.98000000000000000000,对吧?不,我真正得到的是
0.97999999999999887201
(你的结果可能会有所不同).
规范What Every Programmer Should Know About Floating-Point Arithmetic可以向您解释血腥细节.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。