Подтвердить что ты не робот

Прирост работает очень странно

Эта программа должна предоставлять последние 100 цифр любого факториала размера. Однако там что-то странное происходит с counter2 ++ в main(). counter2 увеличивается на +1 каждый раз, когда цикл работает в функции main() (что в 99 раз). Однако это то, что отображается:

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
71
86
90
123
164
196
207
254
300
362
432
471
551
620
630
708
761
772
857
896
985
1036
1100
1116
1207
1209
1280
1356
1417
1452
1512

Counter2 заканчивается как 1512 вместо 100, но если я удаляю либо mult (i), либо carry() из main(), тогда он отображает 100. Почему счетчик2 заканчивается 1512, а не 100?

#include <iostream>

using namespace std;

int numbers[100];
int counter2 = 0;

void init(){
//sets elements 1-99 of numbers[] to 0, increments counter2 by 1, sets numbers[0] = 1
    for (int i = 1; i < 100; i++){
        numbers[i] = 0;
    }
    numbers[0] = 1;
    counter2++;
}

void mult(int x){
//multiplies each element by 1 through n to calculate for !n
//this is used to represent a very large number without using a BigInt library
//the nth element is a placeholder for the n+1 position of the number
//e.g 2nd element represents 100-900 of the number, 4th represents 1000-9000, etc
//carry() is used to take care of overflow, so that it only 1 digit per element
    for (int i = 0; i < 100; i++){
        numbers[i] *= x;
    }
}

void carry(){
//in order to make previous function work, this adds any overflow to the next
//element. e.g: 8 * 4 = 32, 3 is added to numbers[i+1], sets numbers[i] to 2
    int counter = 0;
    for (int i = 0; i < 100; i++){
        if (numbers[i] >= 10){
            counter = numbers[i] / 10;
            numbers[i+1] += counter;
            numbers[i] = numbers[i] % (counter * 10);
        }
    }
}

int main()
{
    init();
    for (int i = 2; i < 101; i++){
    //calculates the last 100 digits of !100, but counter2 ends up being 1512
        mult(i);
        carry();
        counter2++;
        cout << counter2 << endl;
    }
}
4b9b3361

Ответ 1

Вы пишете конец массива numbers в carry():

        numbers[i+1] += counter;

Здесь i может быть 99, и в этом случае numbers[i+1] выходит за пределы.

Технически это undefined поведение. Что на практике происходит, это то, что вы перезаписываете переменную count2, которая, по-видимому, находится в памяти сразу после массива.

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

Ответ 2

В этой строке

 numbers[i+1] += counter;

вы записываете границы массива numbers[100];
при i == 99, изменяя при этом значение int counter2 = 0;, которое (в вашем случае, но не обязательно) находится рядом с числами в памяти.