Каков наилучший способ проверить бесконечность в модуле 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;

И затем добавив в мой модуль оговорку о том, что сначала необходимо загрузить все модули бигнама. Это звучит разумно? Есть ли надежная реализация if_any_bignum... там, или я должен рулон мой?

Ответы

Ответ 1

Math:: BigInt предоставляет метод is_inf. Он может обнаруживать бесконечность как для обычных номеров Perl, включая Perl-встроенный inf, например, возврат 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. Достаточно легко вставить другой код с небольшими изменениями, хотя я бы рекомендовал просто использовать функциональность непосредственно из модуля.