Как я могу обойти ошибку округления, которая вызывает бесконечный цикл в Perl Statistics::Descriptive?

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

Вопрос

Я использую Статистика::Описательная библиотека на Perl для вычисления частотных распределений и решения проблемы с ошибкой округления с плавающей запятой.

Я передаю два значения, 0.205 и 0.205, (взятые из других чисел и спринтированные с ними) в модуль статистики и прошу его вычислить распределение частот, но он застревает в бесконечном цикле.

Проходя через отладчик, я вижу, что он делает:

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+=диапазон) < max)) входит в (по сути) бесконечный цикл.

ДБ<8> вывести $self->{max};
0.205
ДБ<9> вывести $self->{min};
0.205
ДБ<10> вывести $self->{max}-$self->{min};
2.77555756156289е-17

Так что это похоже на проблему округления.Однако я не могу придумать, как исправить это со своей стороны, и я не уверен, что редактирование библиотеки - хорошая идея.Я ищу предложения по обходному пути или альтернативе.

Приветствия, Нил

Это было полезно?

Решение

Я сопровождающий Statistics::Descriptive.Из-за его числовой природы сообщалось о многих проблемах с округлением.Я полагаю, что этот конкретный вариант был исправлен в более поздней версии по сравнению с той, которую вы использовали и которую я недавно выпустил, используя умножение для делений вместо +=.

Пожалуйста, используйте самая актуальная версия из CPAN, и это должно быть лучше.

Другие советы

Не совсем проблема округления;вы можете увидеть более точные значения с помощью чего-то вроде

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

Мне кажется, что в модуле есть недостаток, из-за которого предполагается, что диапазон выборки может быть разделен на части $ partitions;поскольку плавающая точка не обладает бесконечной точностью, это не всегда возможно.В вашем случае минимальные и максимальные значения являются точно смежными представимыми значениями, поэтому не может быть более одного раздела.Я не знаю, для чего именно модуль использует разделы, поэтому я не уверен, как это может повлиять.Другая возможная проблема в модуле заключается в том, что он использует числа в качестве хэш-ключей, что неявно преобразует их в строку, что слегка округляет значение.

Вы можете иметь некоторый успех в борьбе с отмыванием ваши данные через stringization перед подачей модуль:

$data = 0+"$data";

Это, по крайней мере, гарантирует, что два числа, которые (с точностью печати по умолчанию) кажутся равными, на самом деле равны.

Это не должно приводить к бесконечному циклу.Что привело бы к тому, что этот цикл был бы бесконечным, было бы, если $self->{sample_range}/$partitions равно 0.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top