代码之家  ›  专栏  ›  技术社区  ›  NeilInglis

如何解决在Perl的statistics::describative中导致无限循环的舍入错误?

  •  3
  • NeilInglis  · 技术社区  · 15 年前

    我正在使用 Statistics::Descriptive Perl中的库,用于计算频率分布,并针对浮点舍入错误问题进行处理。

    我把两个值,0.205和0.205(取自其他数字和sprintf'd)传递给stats模块,让它计算频率分布,但它陷入了一个无限循环中。

    通过一个调试器,我可以看到它正在做:

    my $interval = $self->{sample_range}/$partitions;
    
    my $iter = $self->{min};
    
    while (($iter += $interval) <  $self->{max}) {
    
      $bins{$iter} = 0;
    
      push @k, $iter;  ##Keep the "keys" unstringified
    
    }
    

    $self->sample_range(范围是max min)返回的是2.77555756156289E-17,而不是如我所料的0。这意味着循环((min+=range)<max))进入一个(所有意图和目的)无限循环。

    DB<8>打印$self->max
    零点二零五
    DB<9>打印$self->分钟
    零点二零五
    db<10>打印$self->max-$self->min
    2.77555756156289E-17

    所以这看起来像一个舍入问题。不过,我想不出怎么解决这个问题,我也不确定编辑图书馆是个好主意。我正在寻找解决方案或替代方案的建议。

    干杯, 尼尔

    3 回复  |  直到 15 年前
        1
  •  6
  •   brian d foy    15 年前

    我是统计学:描述性维护者。由于它的数值性质,许多舍入问题已被报告。我相信这个特别的版本在以后的版本中被修复了,在我最近发布的版本中,通过对除法使用乘法而不是+=。

    请使用 the most up-to-date version 来自CPAN,应该更好。

        2
  •  3
  •   ysth    15 年前

    不完全是舍入问题;您可以看到更精确的值,例如

    printf("%.18g %.18g", $self->{max}, $self->{min});
    

    在我看来,模块中存在一个缺陷,它假定样本范围可以划分为$partitions块;因为浮点不具有无限精度,所以这并不总是可能的。在您的示例中,最小值和最大值正好是相邻的可表示值,因此不能有多个分区。我不知道模块使用分区的确切目的,所以我不确定这会有什么影响。 模块中的另一个可能问题是,它使用数字作为哈希键,而 隐式地将其字符串化,使值稍微四舍五入。

    在提供数据之前,您可能已经成功地通过字符串化清洗了数据。 模块:

    $data = 0+"$data";
    

    这至少可以确保两个(默认打印精度)看起来相等的数字实际上相等。

        3
  •  -1
  •   Chas. Owens    15 年前

    这不应该导致无限循环。如果 $self->{sample_range}/$partitions 是0。