Как лучше всего проверить бесконечность в модуле Perl?

В одном из моих модулей мне приходится иметь дело с концепцией бесконечности. На сегодняшний день я использовал 9**9**9 как положительную бесконечность, и это, кажется, работает хорошо, быстро и похоже на то, что внутреннее устройство Perl использует как бесконечность.

Однако все становится немного рискованно, если пользователь моего модуля решает использовать один из модулей с большими числами (например, use bigint;), а затем они используют inf или Math::BigInt->binf() для представления бесконечности.

В некоторых местах кажется, что это работает нормально, но в других сравнения, которые должны быть верными или должны быть ложными, заканчиваются неверным путем, что затрудняет отслеживание ошибок.

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

Но меня также беспокоит производительность, поскольку некоторые из моих сравнений с бесконечностью происходят в жестких внутренних циклах. Очевидно, что inf из Math::BigInt будет медленнее, чем 9**9**9 (из-за вызова связанных или перегруженных методов при каждом доступе). Кто-нибудь раньше занимался этой проблемой? Если да, то каково было ваше решение?

Я думал об использовании моей собственной константы для бесконечности, определил что-то вроде этого:

use constant INF => if_any_bignum_modules_loaded() 
                    ? Math::BigInt->binf 
                    : 9**9**9;

А затем добавляю в свой модуль предостережение о том, что сначала должны быть загружены любые модули bignum. Это звучит разумно? Есть ли надежная реализация if_any_bignum..., или мне стоит использовать свою?


person Eric Strom    schedule 04.10.2010    source источник
comment
возможный дубликат Как создать или проверить на NaN или бесконечность в Perl?   -  person Ether    schedule 04.10.2010
comment
@Ether = ›пожалуйста, прочтите вопрос перед тем, как проголосовать за закрытие, ни один из ответов на этот вопрос не охватывает этот вопрос ...   -  person Eric Strom    schedule 04.10.2010
comment
хорошо, это было не очень ясно, поскольку вопросы идентичны.   -  person Ether    schedule 04.10.2010
comment
@Ether = ›этот вопрос касается того, как наилучшим образом поддержать конечных пользователей, которые могут или не могут использовать bignum, без снижения производительности для пользователей, которые этого не делают. Связанный вопрос кратко затрагивает проблемы, связанные с bignum в одном из комментариев, но анализ краткий, неполный и не дает решения. Я просмотрел этот вопрос и все остальное, что встречается при поиске [perl] infinity, прежде чем опубликовать этот вопрос.   -  person Eric Strom    schedule 04.10.2010


Ответы (1)


Math :: BigInt предоставляет is_inf метод. Он может определять бесконечность как для обычных чисел Perl, включая встроенные в Perl inf, такие как return by 9**9**9, так и для любых экземпляров Math::Big* или тех волшебных вещей, которые вы получаете, когда используете bigint. Загрузка Math::BigInt практически не связана с накладными расходами - в любом случае, ни с чем не сравнимо с использованием bigint - и является основным модулем с самого начала Perl 5.

use 5.010;
use Math::BigInt;

say Math::BigInt->is_inf(42);
say Math::BigInt->is_inf(9**9**9);
say Math::BigInt->is_inf(Math::BigInt->binf);

__END__
0
1
1

Вы также можете взглянуть на реализацию этого метода, если действительно хотите вообще избежать загрузки Math::BigInt. Достаточно легко встроить в другой код с небольшими изменениями, хотя я бы действительно рекомендовал просто использовать функциональность модуля напрямую.

person rafl    schedule 04.10.2010
comment
Это определенно выглядит как хорошее комплексное решение для всех тестов, не связанных с внутренним циклом. Мне нужно будет провести тест, чтобы увидеть влияние производительности на внутренние циклы. - person Eric Strom; 04.10.2010
comment
Если вы обнаружите, что это слишком медленно для того, что вы делаете, и выясните способ более быстрой реализации тех же функций, я был бы очень рад применить ваши патчи к Math :: BigInt и отправить их в CPAN. - person rafl; 04.10.2010
comment
Звучит хорошо, я посмотрю, что я могу сделать. Я предполагаю, что изменение всех совпадений регулярных выражений на вызовы index было бы началом. - person Eric Strom; 04.10.2010
comment
= ›inf_nan.t нужен еще один тест, Math::BigInt->is_inf(9**9**9) кажется, не работает с клубничным Perl, по крайней мере, на 64-битной платформе. базовый clib возвращает 1.#INF для 9**9**9, который BigInt сопоставляется с NaN. тот же результат на 5.8.9 и 5.12 - person Eric Strom; 06.10.2010