C:f> 0 vs Perl:$ f> 0?

时间:2011-03-30 17:07:45

标签: c perl

此C代码显示Fibonacci数字:

#include <stdio.h>
int main(){
   for (long long int t, i=1, p=1, f=2; f>0 ; i++, t=f, f+=p, p=t)
      printf("%lli: %lli\n", i, f); 
   }

按照预期,它不需要对迭代次数进行硬编码就会停止。

Perl中的代码试图使用相同的技术:

my $t;
my $p=1;
my $f=2;
for ($i=1; $f>0; $t=$f, $f+=$p, $p=$t, $i++){
   printf("%i: %i\n", $i, $f);
   if ($i>50){exit;}
   }

但它没有像预期的那样停止,当价值溢出45而不是 51额外检查开始时。

44: 1836311903
45: -1323752223
46: -1
47: -1
48: -1
49: -1
50: -1
51: -1

Perl做了什么不同导致这种情况?

5 个答案:

答案 0 :(得分:5)

Perl使用任意类型,根据需要在无符号整数和有符号整数与浮点之间切换。但是,printf强制将任意类型转换为整数。请尝试使用%s代替:

my $t;
my $p=1;
my $f=2;
for ($i=1; $f>0; $t=$f, $f+=$p, $p=$t, $i++){
   printf("%i: %s\n", $i, $f);
   if ($i>50){exit;}
}

大负数实际上存储在perl中作为无符号整数; -1是过大的浮点数被截断为最大无符号整数,但后来被视为%i签名。

答案 1 :(得分:3)

您的C签名整数代码从大数字溢出到负数并停止。 Perl使用浮动pt数学可以让它以更低的精度进行更多的迭代,而且我认为它不会在数字变得非常大时回滚。

答案 2 :(得分:2)

由于编程习惯不佳,您的c代码实际上正在退出。您依赖flong long int,其上限为9.22337204×10 ^ 18。当你循环到第91次迭代时,f变为1.22001604×10 ^ 19,它会溢出并变为负数。

Perl代码继续快乐,但正如您应该注意到的那样,最终您将打印出一系列-1 s,这应该是您的代码不正确的线索。

如果你对整数大小没有任何限制,你的c代码会永远存在,这可能不是你想要的。对于像Fibonacci序列这样的无限序列,你想要有一个暂停条件。

答案 3 :(得分:1)

Perl代码可能默认为浮点运算。这似乎是this所表明的。尝试在那里投掷use integer;

答案 4 :(得分:1)

您在Perl中使用32位整数,在C中使用更大的整数.32位不足以存储这些数字。您可以重建Perl以使用64位整数,或者您可以让Perl使用浮动指针编号(53位整数而不丢失),如同建议的那样。