Каков наилучший способ проверить бесконечность в модуле Perl? - PullRequest
13 голосов
/ 04 октября 2010

В одном из моих модулей я имею дело с концепцией бесконечности. До настоящего времени я использовал 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... или я должен развернуть свою собственную?

1 Ответ

9 голосов
/ 04 октября 2010

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

...