Como posso trabalhar em torno de um erro de arredondamento que faz com que um loop infinito em Estatística do Perl :: descritiva?

StackOverflow https://stackoverflow.com/questions/944553

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};
0,205
DB <9> imprimir $ self -> {min};
0,205
DB <10> imprimir $ self -> {max} - $ self -> {min};
2.77555756156289e-17

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

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top