Проблема при попытке печати добавленных элементов массива в c - PullRequest
0 голосов
/ 25 февраля 2019

Я пытался создать массив, содержащий числа Фибоначчи в Си, но у меня возникли проблемы.Я не могу получить все элементы, и некоторые элементы неправильно рассчитаны, и я не знаю, где я иду, я иду неправильно.

#include <stdio.h>
int main(void){
    int serie[]={1,1},sum=0,size=2;
    while(size<=4000000){
        serie[size]=serie[size-1]+serie[size-2];
        printf("%d\n",serie[size-1]);
        size+=1;
    }
    return 0;
}

Вывод:

1
2
4
6
11
17
28
45
73
118
191
309
500
809
1309
2118
3427
5545
8972
14517
23489
38006
61495
99501
160996
260497
421493
681990
1103483
1785473
2888956
4674429
7563385
12237814
19801199
32039013
51840212
83879225
135719437
219598662
355318099
574916761
930234860
1505151621
-1859580815
-354429194
2080957287
1726528093
-487481916
1239046177
751564261
1990610438
-1552792597
437817841
-1114974756
-677156915
-1792131671
1825678710
33547039
1859225749
1892772788
-542968759
1349804029
806835270
-2138327997
-1331492727
825146572
-506346155
318800417
-187545738
131254679
-56291059
74963620
18672561
93636181
112308742
205944923
318253665
524198588
842452253
1366650841
-2085864202
-719213361
1489889733
770676372
-2034401191
-1263724819
996841286
-266883533
729957753
463074220
1193031973
1656106193
-1445829130
210277063
-1235552067
-1025275004
2034140225
1008865221
-1251961850
-243096629
-1495058479
-1738155108
1061753709
-676401399
385352310
-291049089
94303221
-196745868
-102442647
-299188515
-401631162
-700819677
-1102450839
-1803270516
1389245941
-414024575
975221366
561196791
1536418157
2097614948
-660934191

--------------------------------
Process exited after 2.345 seconds with return value 3221225477
Press any key to continue . . .

Я не понимаю, почему он дает такой вывод.

Ответы [ 4 ]

0 голосов
/ 25 февраля 2019

У вас есть две проблемы:

  • Вам нужно выделить больше места в serie, столько, сколько вы собираетесь использовать
  • В конце концов числа Фиби станут слишком большимичтобы поместиться в целое число, даже 64-битное целое число без знака (длинный длинный без знака), я думаю, что 90 или около того - это максимум

См. модифицированный код:

#include <stdio.h>

// Set maximum number of fib numbers
#define MAX_SIZE 90

int main(void) {
    // Use 64 bit unsigned integer (can't be negative)
    long long unsigned int serie[MAX_SIZE];
    serie[0] = 1;
    serie[1] = 1;

    int sum = 0;
    int size = 0;

    printf("Fib(0): %llu\n", serie[0]);
    printf("Fib(1): %llu\n", serie[1]);

    for (size = 2; size < MAX_SIZE; size++) {
        serie[size] = serie[size-1] + serie[size-2];

        printf("Fib(%i): %llu\n", size, serie[size]);
    }
    return 0;
}

Как вытолько распечатывает числа, вам не нужно хранить все из них (только два предыдущих числа), но на самом деле не имеет значения, есть ли только 90.

0 голосов
/ 25 февраля 2019

У вас целочисленное переполнение, потому что размер int на определенном уровне недостаточно велик для размещения чисел, поэтому число оборачивается вокруг размера и дает ложные значения.

Ваша программа должна выглядеть следующим образом:

#include <stdio.h>
int main(void){
    long long unsigned series[100] = {1,1};
    int size = 2;

    while(size < 100){
        series[size] = series[size-1] + series[size-2];
        printf("%llu\n", series[size-1]);
        size += 1;
    }

    return 0;
}

Хотя размер long long unsigned на определенном уровне также ограничен такими очень большими числами в Фибоначчи.Таким образом, это приведет к печати более правильных чисел, но также будет переполнено на определенном уровне.Он переполнится, когда число превысит эту константу ULLONG_MAX, объявленную в limits.h.

0 голосов
/ 25 февраля 2019

Проблема с этим кодом:

#include <stdio.h>
int main(void){
    int serie[]={1,1},sum=0,size=2;
    while(size<=4000000){
        serie[size]=serie[size-1]+serie[size-2];
        printf("%d\n",serie[size-1]);
        size+=1;
    }
    return 0;
}

... заключается в том, что он пытается сохранить очень длинный ряд чисел (4 миллиона) в очень короткий массив (2 элемента).Массивы имеют фиксированный размер.Изменение переменной size не влияет на размер массива serie.

Выражение serie[size]=... хранит числа вне границ массива каждый раз, когда выполняется , потому чтотолько допустимые значения индекса массива - 0 и 1. Это приводит к неопределенному поведению , и, честно говоря, вам повезло только увидеть странный вывод.

Есть несколько возможных решений.Тот, который меняет ваш код меньше всего, это просто расширить массив.Обратите внимание, что я сделал ее статической, а не автоматической переменной, потому что ваша реализация, вероятно, не будет поддерживать что-то такого размера в своем стеке.

#include <stdio.h>

int serie[4000000]={1,1};

int main(void){
    int size=2;
    while(size<4000000){ // note strict less-than: 4000000 is not a valid index
        serie[size]=serie[size-1]+serie[size-2];
        printf("%d\n",serie[size-1]);
        size+=1;
    }
    return 0;
}

Более общее решение - сохранить текущий термин идва предыдущих термина в серии как три отдельных целых числа.Это немного дороже в вычислительном отношении, но не требует огромных требований к памяти.

#include <limits.h>
#include <stdio.h>

int main(void)
{
    int term0=0, term1=1, term2;
    while(1)
    {
        if (term0 > INT_MAX - term1) break;// overflow, stop
        term2 = term0 + term1;

        printf("%d\n",term2);
        term0 = term1;
        term1 = term2;
    }
    return 0;
}

Это также имеет то преимущество, что он не будет печатать числа, которые "обернуты" в результате превышенияпределы того, что может быть представлено в «int».Конечно, вы можете легко выбрать другой тип данных, чтобы получить более длинную последовательность допустимых выходных данных.

0 голосов
/ 25 февраля 2019
int serie[]={1,1}

Объявляет массив из двух элементов.Поскольку массив имеет два элемента и индексы начинаются с нуля, он имеет действительные индексы - 0 и 1, т.е.serie[0] - первый элемент, serie[1] - второй элемент.

int size=2;
while(..) {
   serie[size]= ...
   size+=1;
}

Когда size начинается 2, выражение serie[2] = недопустимо.В массиве нет третьего элемента, и он записывает данные в неизвестную область памяти.Выполнение такого действия неопределенное поведение .Там может быть какая-то другая переменная, какая-то системная переменная или память другой программы, или она может порождать носовых демонов.Он не определен.

Если вы хотите сохранить выходные данные в массиве, вам нужно убедиться, что в массиве достаточно элементов для хранения ввода.

И совет:

int serie[4000000];

может не работать, так как попытается выделить 40000000 * sizeof(int), что при условии sizeof(int) = 4 составляет 15,2 мегабайта памяти.Некоторые системы не позволяют выделять столько памяти в стеке, поэтому вам следует перейти к динамическому распределению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...