Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Increment working very strangely

Tags:

c++

increment

This program is supposed to give to the last 100 digits of any size factorial. However, there's something weird going on with the counter2++ in main(). counter2 is incremented +1 for each time the loop runs in the main() function (which is 99 times). However this is what is displayed:

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 ends up being 1512 instead of 100, but if I remove either mult(i) or carry() from main() then it displays 100. Why does counter2 end up being 1512 and not 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's 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;
    }
}
like image 859
xyz Avatar asked Apr 11 '13 06:04

xyz


1 Answers

You are writing past the end of the numbers array in carry():

        numbers[i+1] += counter;

Here, i can be 99, in which case numbers[i+1] is out of bounds.

Technically, this is undefined behaviour. What happens in practice is that you overwrite the count2 variable, which happens to sit in memory right after the array.

One nasty thing about memory bugs is that they can go symptomless for a long time, and then surface in the worst possible circumstances. valgrind is a great tool for detecting problems of this type.

like image 113
NPE Avatar answered Sep 23 '22 10:09

NPE