如何计算perl的方差?

我想计算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可以向您解释血腥细节.

相关文章

1. 如何去重 #!/usr/bin/perl use strict; my %hash; while(...
最近写了一个perl脚本,实现的功能是将表格中其中两列的数据...
表的数据字典格式如下:如果手动写MySQL建表语句,确认麻烦,...
巡检类工作经常会出具日报,最近在原有日报的基础上又新增了...
在实际生产环境中,常常需要从后台日志中截取报文,报文的形...
最近写的一个perl程序,通过关键词匹配统计其出现的频率,让...