Como posso trabalhar em torno de um erro de arredondamento que faz com que um loop infinito em Estatística do Perl :: descritiva?
-
09-09-2019 - |
Pergunta
Eu estou usando a biblioteca Statistics :: Descriptive em Perl a frequência calcular distribuições e chegando contra um ponto flutuante arredondamento problema de erro.
eu passar em dois valores, 0,205 e 0,205, (tirado de outros números e sprintf'd àqueles) com as estatísticas módulo e pedir-lhe para calcular a distribuição de frequência mas está ficando preso em um loop infinito.
Percorrendo com um depurador eu posso ver que ele está fazendo:
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 (O intervalo é max-min) está retornando 2.77555756156289e-17 em vez de 0 como seria de esperar. Isto significa que o circuito ((min + = gama) DB <8> imprimir $ self -> {max}; Portanto, este parece um problema de arredondamento. Eu não posso pensar como corrigir isso no meu lado embora, e eu não estou certo de editar a biblioteca é uma boa idéia. Eu estou procurando sugestões de uma solução ou alternativa. Cheers,
Neil
0,205
DB <9> imprimir $ self -> {min};
0,205
DB <10> imprimir $ self -> {max} - $ self -> {min};
2.77555756156289e-17
Solução
Eu sou o Estatísticas :: mantenedor descritiva. Devido à sua natureza numérica, muitos problemas de arredondamento têm sido relatados. Eu acredito que este em particular foi corrigido em uma versão posterior para o que você estava usando que eu lançou recentemente, através da utilização de multiplicação para as divisões em vez de + =.
Por favor, use o mais up-to-date versão do CPAN, e ele deve ser melhor.
Outras dicas
Não é exatamente um problema de arredondamento; você pode ver os valores mais precisos com algo como
printf("%.18g %.18g", $self->{max}, $self->{min});
Parece-me que há uma falha no módulo onde ele assume a faixa de amostras pode ser dividido em partições $ peças; porque o ponto flutuante não tem precisão infinita, isso nem sempre é possível. No seu caso, os valores mínimo e máximo são valores representáveis ??exatamente adjacentes, de modo que não pode haver mais de uma partição. Eu não sei o que exatamente o módulo está usando as partições para, então eu não sei qual é o impacto disso pode ser. Outro possível problema no módulo é que ela está usando números como chaves de hash, os quais implicitamente stringifies-los que arredonda um pouco o valor.
Você pode ter algum sucesso na lavagem de seus dados através stringization antes de alimentá-lo para o módulo:
$data = 0+"$data";
Esta, pelo menos, garantir que dois números que (com a precisão padrão de impressão) parecem iguais são realmente iguais.
Isso não deve causar um loop infinito. O que faria com que o loop para ser infinito seria se $self->{sample_range}/$partitions
é 0.