Comment puis-je travailler autour d'une erreur de ronde qui provoque une boucle infinie dans les statistiques de Perl :: descriptif?

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

Question

J'utilise le Statistiques :: bibliothèque descriptive en Perl pour calculer la fréquence distributions et à venir contre un problème d'erreur d'arrondi en virgule flottante.

je passe deux valeurs, 0,205 et 0,205, (provenant d'autres numéros et sprintf'd à ceux) au module de statistiques et de lui demander de calculer la distribution de fréquence, mais il est coincé dans une boucle infinie.

Parcourant avec un débogueur je peux voir que ça fait:

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 (La plage est max-min) est de retour 2.77555756156289e-17 plutôt que 0 comme je pense. Cela signifie que la boucle ((min + = intervalle)

DB <8> print $ self -> {max};
0.205
  DB <9> print $ self -> {min};
0.205
  DB <10> print $ self -> {max} - $ self -> {min};
2.77555756156289e-17

Cela ressemble à un problème d'arrondi. Je ne peux pas penser comment résoudre ce problème de mon côté cependant, et je ne suis pas sûr que l'édition de la bibliothèque est une bonne idée. Je cherche des suggestions d'une solution ou alternative.

Cordialement, Neil

Était-ce utile?

La solution

Je suis Statistique :: mainteneur descriptif. En raison de sa nature numérique, de nombreux problèmes d'arrondissement ont été signalés. Je crois que celui-ci en particulier a été fixé dans une version ultérieure à celle que vous utilisiez que je récemment publié, en utilisant la multiplication des divisions au lieu de + =.

la version la plus à jour du CPAN, et il devrait être mieux.

Autres conseils

Pas exactement un problème d'arrondi; vous pouvez voir les valeurs plus précises avec quelque chose comme

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

Attend pour moi comme il y a une faille dans le module où il assume la plage d'échantillon peut être divisé en partitions $ morceaux; parce que le point flottant n'a pas une précision infinie, ce n'est pas toujours possible. Dans votre cas, les valeurs min et max sont des valeurs représentables exactement adjacentes, donc il ne peut pas être plus d'une partition. Je ne sais pas exactement ce que le module utilise les partitions pour, donc je ne suis pas sûr de ce que l'impact de cela peut être. Un autre problème possible dans le module est qu'il utilise des nombres comme clés de hachage, qui les stringifies implicitement qui arrondit légèrement la valeur.

Vous pouvez avoir un certain succès dans le blanchiment de vos données par stringization avant de le nourrir au module:

$data = 0+"$data";

Cela permettra au moins faire en sorte que deux numéros (avec la précision d'impression par défaut) apparaissent égaux sont réellement égaux.

Cela ne devrait pas provoquer une boucle infinie. Quelle serait la cause de cette boucle soit infinie serait si $self->{sample_range}/$partitions est 0.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top