This C code displays Fibonacci numbers:
#inclu开发者_JAVA技巧de <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);
}
As intended it stops without having to hard code the number of iterations.
The code in Perl is attempting to use the same technique:
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;}
}
But it does not stop as expected, at the point the value overflows at 45 rather than at 51 when the extra check kicks in.
44: 1836311903
45: -1323752223
46: -1
47: -1
48: -1
49: -1
50: -1
51: -1
What does Perl do differently that causes this?
Perl uses arbitrary types, switching between unsigned and signed integers and floating point as needed. printf, however, is forcibly converting the arbitrary type to an integer. Try using %s instead:
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;}
}
The large negative number is in fact stored in perl as an unsigned integer; the -1's are too large floating point numbers being truncated to the maximum unsigned integer but then treated as signed by %i.
Your C signed integer code overflows from a large number to a negative number and stops. Perl's use of floating pt math lets it go through more iterations with reduced precision, and I don't think it'll wrap around when the number gets really big.
Your c
code is actually exiting because of poor programming practice. You're relying on f
being a long long int
, which has an upper limit of 9.22337204 × 10^18. When you loop around to the 91st iteration f
becomes 1.22001604 × 10^19, which overflows and becomes negative.
The Perl code continues on merrily but, as you should notice, eventually you'll print out a sequence of -1
s, which should be a clue that your code is incorrect.
If you didn't have any limits on integer size your c
code would go on forever, which is probably not what you want. For infinite sequences like the Fibonacci sequence you want to have a halting condition.
Possibly the Perl code defaults to floating-point arithmetic. That seems to be what this indicates. Try throwing a use integer;
in there.
You are using 32-bit integers in Perl and larger integers in C. 32-bits are not enough to store those numbers. You could rebuild your Perl to use 64-bit integers, or you could let Perl use floating pointer numbers (53-bit integers with no loss) as ysth suggested.
精彩评论