此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做了什么不同导致这种情况?
答案 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
代码实际上正在退出。您依赖f
为long 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位整数而不丢失),如同建议的那样。