2010-11-12 6 views
2
$str =sprintf "%014ld", "2555600000"; 
print $str; 

Cela me donne le résultat:Quelle est la raison de cette erreur de formatage Perl?

-0001739367296 

un nombre négatif. Y a-t-il une raison à ce comportement?

+2

Il ne pas pour moi. Travaillez-vous sur une machine 32 bits? –

+0

oui mais le code similaire exécuté en java m'a donné un résultat correct – sab

Répondre

11

2555600000 est trop grand pour tenir dans un entier signé 32 bits. Convertis en binaire, 10011000 01010011 01011100 10000000 correspond à -0001739367296 lorsqu'il est interprété comme un entier signé de 32 bits.

Vos options sont:

my $str = sprintf("%014u", 2555600000);  # unsigned integer 
my $str = sprintf("%014.0f", 2555600000); # floating point 
my $str = sprintf("%014s", 2555600000);  # string 

Le premier travaille pour ce numéro, mais pas pour un nombre beaucoup plus élevé. Le second peut devenir inexact pour les nombres très élevés. (Mais avec le "double" standard à virgule flottante, vous devriez être précis pour les 14 chiffres que vous utilisez, le troisième étant le plus simple, il suffit de le traiter comme une chaîne et d'oublier qu'il s'agit d'un numéro

voir combien de bits votre version utilise, vous pouvez exécuter perl -V Exemple de sortie:..

... 
intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234 
... 

donc mon Perl utilise 4 octets, 32 bits, entiers

5
$ perl -e '$str =sprintf "%014ld", "2555600000"; print $str, "\n";' 
00002555600000 

Ça marche pour moi. Cependant, le nombre que vous donnez est plus grand qu'un entier signé de 32 bits peut contenir, alors peut-être que votre résultat signifie que vous êtes sur une machine 32 bits?

+0

32 bits Perl c'est. Pas la machine. – n0rd

4

Malheureusement, les modificateurs de printf sont assez étroitement couplé aux types C sous - jacents (bien que les tailles soient déterminées par perl - ld ne soit pas différente de d, en dessous, perl utilisera les quali fier taille de int il est construit pour). Donc,% d va convertir un nombre en int signé,% u en un entier non signé, même si perl sait ce qu'il est réellement.

Vous êtes souvent mieux juste en utilisant% s:

$ perl -wle'printf "%014s\n%014d\n", "2555600000", "2555600000";' 
00002555600000 
-0001739367296 
+0

+1 pour utiliser '% 014s'. Je l'ai volé et ajouté à ma réponse. :-) – mscha

Questions connexes