Question

Sur une plate-forme Windows 32 bits, je dois lire des chiffres qui, inattendus, peuvent avoir des valeurs aussi élevées que 99 999 999 999, mais pas plus. Essayer de sprintf ("% 011d", $ myNum) génère un débordement: -2147483648.

Je ne peux pas utiliser le module BigInt car, dans ce cas, je devrais modifier profondément le code. Je ne peux pas gérer le format sous forme de chaîne, sprintf ("% 011s", $ numero) , car le signe moins n'est pas traité correctement.

Comment puis-je gérer cela? Peut-on aider à emballer / décompresser?

Était-ce utile?

La solution

Essayez de le formater en tant que float sans partie de fraction:

$ perl -v
This is perl, v5.6.1 built for sun4-solaris
...

$ perl -e 'printf "%011d\n", 99999999999'
-0000000001

$ perl -e 'printf "%011.0f\n", 99999999999'
99999999999

Autres conseils

Oui, l’un des angles morts numériques de Perl est le formatage; Perl gère automatiquement la représentation des nombres sous forme d’entiers ou de flottants, mais les contraint ensuite dans l'un ou l'autre lorsque les formats numériques printf sont utilisés, même si ce n'est pas le cas approprié. Et printf ne gère pas vraiment BigInts (sauf en traitant en les convertissant en un nombre, avec perte de précision).

En utilisant% s au lieu de% d avec un nombre quelconque, vous n'êtes pas sûr que ce sera dans un La plage est une bonne solution de contournement, sauf que vous notez des nombres négatifs. Gérer ceux-là, vous allez devoir écrire du code Perl.

Je ne suis pas un expert en Perl, et peut-être me manque-t-il une sorte de traitement automatique des bignums ici, mais n'est-ce pas simplement un cas de dépassement d'entier? Un entier 32 bits ne peut pas contenir de nombres aussi grands que 99 999 999 999.

Quoi qu’il en soit, j’obtiens le même résultat avec Perl v5.8.8 sur ma machine Linux 32 bits et il semble que printf avec "% d" ne gère pas les grands nombres.

Je pense que votre copie de Perl doit être brisée, elle provient de la version 5.10 de CygWin:

pax$ perl -e 'printf("%011d\n", 99999999999);'
99999999999

pax$ perl -v

This is perl, v5.10.0 built for cygwin-thread-multi-64int
(with 6 registered patches, see perl -V for more detail)

Copyright 1987-2007, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

Quelle version utilisez-vous (sortie de perl -v )?

Il se peut que vous deviez obtenir une version 64 bits de Perl [et éventuellement une nouvelle machine de production 64 bits] (notez le "cygwin-thread-multi-64int" ) dans ma sortie. ). Cela évitera au moins la nécessité de changer le code.

J'affirme ceci en partant du principe que vous ne voulez pas changer le code de façon importante (c’est-à-dire que vous craignez de casser des choses). La solution de nouveau matériel, bien que un peu coûteuse, ne nécessitera presque certainement pas de changer le logiciel du tout . Cela dépend de vos priorités.

Une autre possibilité est que Perl lui-même stocke le numéro correctement mais l’affiche mal en raison d’un code printf () . Dans ce cas, vous pouvez essayer:

$million = 1000000;
$bignum = 99999999999;
$firstbit = int($bignum / $million);
$secondbit = $bignum - $firstbit * million;
printf ("%d%06d\n",$firstbit,$secondbit);

Mettez cela dans une fonction et appelez-la pour renvoyer une chaîne, telle que:

sub big_honkin_number($) {
    $million = 1_000_000;
    $bignum = shift;
    $firstbit = int($bignum / $million);
    $secondbit = $bignum - $firstbit * $million;
    return sprintf("%d%06d\n", $firstbit, $secondbit);
}
printf ("%s", big_honkin_number (99_999_999_999));

Notez que j'ai testé cela, mais sur la plate-forme 64 bits - vous devrez faire votre propre test sur 32 bits, mais vous pouvez utiliser le facteur de mise à l'échelle de votre choix (y compris plus de deux segments si nécessaire).

Mise à jour: Cette astuce big_honkin_number () fonctionne correctement sur un Perl 32 bits, il semble donc que est le printf () fonctions qui vous gênent:

pax@pax-desktop:~$ perl -v

This is perl, v5.8.8 built for i486-linux-gnu-thread-multi

Copyright 1987-2006, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

pax@pax-desktop:~$ perl qq.pl
99999999999
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top