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

這給我結果:這個Perl格式錯誤的原因是什麼?

-0001739367296 

負數。是否有這種行爲的原因?

+2

它確實不適合我。你在32位機器上工作嗎? – 2010-11-12 16:51:14

+0

是的,但在java中運行的類似代碼給了我正確的結果 – sab 2010-11-12 16:53:09

回答

11

2555600000太大而不適合32位有符號整數。 轉換爲二進制,它是10011000 01010011 01011100 10000000,當解釋爲有符號的32位整數時,它代表-0001739367296

的選項有:

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

第一個適用於這個數字,而不是更高的數字。第二個對於很高的數字可能會變得不準確。 (但是對於標準的浮點「double」,你應該很容易準確地使用你的14位數字,第三個可能是最簡單的,只要把它當作一個字符串,並且忘記它是一個數字。

To看到你的版本是多少位使用,你可以運行perl -V輸出示例:。所以我的Perl是使用4個字節,32位,整數

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

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

它適用於我。然而,你給出的數字大於一個32位有符號整數可以容納,所以也許你的結果意味着你在一臺32位機器上?

+0

它是32位的Perl。不是機器。 – n0rd 2010-11-13 08:45:02

4

不幸的是,printf的修飾符是相當與底層C類型緊密結合(雖然大小由perl-ld確定,與d相同,在下面,perl將使用quali爲它構建的int的更大尺寸)。

因此,即使perl知道它實際是哪一個,%d也會將一個數字轉換爲一個帶符號的int,%u轉換爲一個unsigned int。

你通常能夠更好地只用%S:

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

使用'%014s' +1。我偷了它,並將其添加到我的答案。 :-) – mscha 2010-11-12 17:11:55