2010-10-04 5 views
13

Dans l'un de mes modules, je dois traiter du concept de l'infini. À ce jour, j'ai utilisé 9**9**9 comme infini positif, et cela semble bien fonctionner, est rapide, et semble être ce que les internes de Perl utilisent comme infini.Quelle est la meilleure façon de vérifier l'infini dans un module Perl?

Cependant, les choses deviennent un peu casse-gueule si un utilisateur de mon module décide d'utiliser l'un des grands modules numériques (comme use bigint;), puis ils utilisent inf ou Math::BigInt->binf() pour représenter l'infini.

Dans certains endroits, cela semble fonctionner correctement, mais dans d'autres, les comparaisons qui devraient être vraies ou qui devraient être fausses finissent dans le mauvais sens, ce qui rend difficile le repérage des bogues.

Je voudrais soutenir les diverses autres notions de l'infini avec quelque chose qui fonctionnera avec les nombres perl normaux et les nombres de précision arbitraires.

Mais j'ai aussi des inquiétudes sur les performances car certaines de mes comparaisons à l'infini se produisent dans des boucles internes serrées. De toute évidence inf de Math::BigInt va être plus lent que 9**9**9 (en raison de l'appel de méthodes liées ou surchargées sur chaque accès). Est-ce que quelqu'un a déjà traité ce problème par le passé? Si oui, quelle était votre solution?

J'ai pensé à utiliser ma propre constante pour l'infini, quelque chose défini comme ceci:

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

Et puis en ajoutant la mise en garde à mon module que les modules de BigNum doivent être chargés en premier. Est-ce que cela semble raisonnable? Y at-il une implémentation fiable de if_any_bignum... là-bas, ou devrais-je rouler le mien?

+0

duplication possible de [Comment créer ou tester NaN ou infini en Perl?] (Http://stackoverflow.com/questions/1185822/how-do--create-or-test-for-nan- or-infinity-in-perl) – Ether

+1

@Ether => s'il vous plaît lire la question avant de voter pour fermer, aucune des réponses à cette question ne couvre cette question ... –

+0

ok, ce n'était pas très clair, car les questions sont identiques . – Ether

Répondre

8

Math::BigInt fournit une méthode is_inf. Il peut détecter l'infini pour les deux nombres Perl réguliers, y compris les intégrés de Perl, tels que le retour par 9**9**9, ainsi que n'importe quel type d'instance Math::Big* ou les trucs magiques que vous obtenez lorsque vous utilisez bigint. Chargement Math::BigInt est livré avec peine une surcharge du tout - pas comparable à l'utilisation bigint de toute façon - et est un module de base depuis le début de 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 

Vous pouvez également jeter un oeil à la mise en œuvre de cette méthode si vous voulez vraiment éviter de charger Math::BigInt du tout. Il est assez facile de s'insérer dans un autre code avec de légères modifications, bien que je recommande vraiment d'utiliser directement les fonctionnalités du module.

+0

Cela ressemble vraiment à une bonne solution fourre-tout pour tous les tests en boucle non-interne. Je vais devoir faire un benchmark pour voir l'impact sur les performances des boucles internes. –

+1

Si vous trouvez que c'est trop lent pour ce que vous faites et trouvez un moyen d'implémenter la même fonctionnalité plus rapidement, je serais très heureux d'appliquer vos correctifs à Math :: BigInt et de les envoyer au CPAN. – rafl

+1

Ça sonne bien, je vais voir ce que je peux faire. J'imagine que changer tous les matchs regex en appels à 'index' serait un début. –

Questions connexes