这是查找第 n 个斐波那契数的最后一位数字的代码
#include <stdio.h>
int main() {
long i, j, fib[1000];
fib[0] = 0;
fib[1] = 1;
scanf("%li", &j);
for(i = 2; i != 1000; i++)
{
fib[i] = (fib[i - 2] + fib[i - 1]) % 10;
}
printf("%li", fib[j]);
return 0;
}
它显示分段错误。我该如何解决它?
我能看到这不起作用的唯一原因是您输入的数字超出了0 <= j <= 999
范围。这是由于数组变量的限制:long fib[1000]
。
可以通过以下两种方式之一解决此问题,具体取决于您的需要:
- 您可以添加检查以确保输入值
j
在范围内,如果不是,则要求输入另一个数字。 - 您可以停止使用数组变量,而只使用三个变量:一个用于存储当前值,另外两个用于存储前两个值。这些将在您计算时更新。此方法仍使用循环。
#1 是最容易实现的,如下所示:
while (1)
{
printf("j > ");
scanf(" %li", &j);
if (0 <= j <= 999)
{
break;
}
}
#2 有点复杂,但它有效地删除了j
必须小于 1000 的任意限制(并更改限制,使j
必须小于LONG_MAX
):
// num_cache[0] is the number before the previous number
// num_cache[1] is the previous number to the current number
long num_cache[2] = { 0, 0 };
long current_fib = 1;
for (i = 2; i < j; i++)
{
// Push back the numbers
num_cache[0] = num_cache[1];
num_cache[1] = current_fib;
// Calculate the new number
current_fib = (num_cache[0] + num_cache[1]) % 10;
}
这些解决方案之一应该可以解决您的问题。
分割错误似乎是由于对输入值的检查不充分而发生的。
如果程序的输入不是有效的数字,则调用
scanf()
后j
的值将保持不变。由于此变量未初始化,因此当您尝试访问fib[]
数组的第 j 个元素时,这将导致未定义的行为。如果 j 的值小于零或大于 999,则在退出
for()
循环时,您将访问不存在的fib[]
成员。在继续之前,代码应检查j
是否有效。
下面是您的代码,其中包含一些修改以实现这些保护措施并将"幻数"1000 移动到 #defined 值。
#include <stdio.h>
#define FIBONACCI_LIMIT 1000L
int main(){
long i, j, fib[FIBONACCI_LIMIT];
fib[0] = 0;
fib[1] = 1;
if (scanf("%li", &j) != 1)
{
fprintf(stderr, "Invalid inputn");
return 1;
}
if (j<0 || j>=FIBONACCI_LIMIT)
{
fprintf(stderr, "Number must be in range 0 <= n < %lin", FIBONACCI_LIMIT);
return 2;
}
for(i=2; i!=1000; i++)
{
fib[i] = (fib[i-2] + fib[i-1])%10;
}
printf("%lin", fib[j]);
return 0;
}
可以通过完全删除fib[]
数组来改进代码,因为当您只需要计算一个值时,不需要存储 1000 个值。此外,斐波那契数列中数字的最后一位数字形成了 60 个值的重复模式,因此您的第一步应该是将j
替换为j % 60
。下面是代码的改进版本,它将与任何能够适应long
整数的非负输入一起使用:
#include <stdio.h>
int main() {
long i, j, t, f0=0, f1=1;
if (scanf("%li", &j) != 1)
{
fprintf(stderr, "Invalid inputn");
return 1;
}
if (j < 0)
{
fprintf(stderr, "Number must be non-negativen");
return 2;
}
j %= 60;
for (i=0; i<j; i++)
{
t = f0;
f0 = f1;
f1 = (f1 + t) % 10;
}
printf("%lin", f0);
return 0;
}
您没有显示输入的变量j
的值。
考虑到下一个斐波那契数在循环中计算不正确。
如果使用整数类型unsigned long long
则此类型的对象只能容纳 93 个斐波那契数。
该程序可能看起来像
#include <stdio.h>
#define N 100
int main(void)
{
while ( 1 )
{
unsigned long long fib[N] = { 0, 1 };
unsigned int n;
printf( "Enter a sequantial number of a fibonacci number (0 - exit): " );
if ( scanf("%u", &n) != 1 || n == 0 ) break;
unsigned int i = 2;
for (; i < N && i <= n && fib[i-1] <= fib[i-2] + fib[i-1]; i++)
{
fib[i] = fib[i - 2] + fib[i - 1];
}
if (n < i)
{
printf("#%u: %llu %llun", n, fib[n], fib[n] % 10);
}
else
{
puts("Too big fibonacci number");
}
}
return 0;
}
它的输出可能看起来像
Enter a sequantial number of a fibonacci number (0 - exit): 1
#1: 1 1
Enter a sequantial number of a fibonacci number (0 - exit): 2
#2: 1 1
Enter a sequantial number of a fibonacci number (0 - exit): 3
#3: 2 2
Enter a sequantial number of a fibonacci number (0 - exit): 93
#93: 12200160415121876738 8
Enter a sequantial number of a fibonacci number (0 - exit): 94
Too big fibonacci number
Enter a sequantial number of a fibonacci number (0 - exit): 0