Переполнение происходит из-за добавления?

Здравствуйте и извините за хромое название этого поста, просто не смог найти лучшего.

Итак, я решаю упражнение Codility под названием NumberOfDiscIntersections. Решение требует некоторой базовой сортировки и некоторых незначительных арифметических операций. Я добился результата 93%, и только один тест не работает. Описание, которое они предоставляют, следующее:

Например, для ввода [1, 2147483647, 0] решение вернуло неверный ответ (получено -1, ожидалось 2).

О проблеме можно узнать здесь.

И вот мое решение:

typedef long long int my_type; //can't use unsigned!
#define LIMIT 10000000

//method used by qsort()
int comp(const void* left, const void* right) {
    my_type arg1 = *(const my_type*)left;
    my_type arg2 = *(const my_type*)right;

    if(arg1 < arg2) return -1;
    if(arg2 < arg1) return 1;
    return 0;
}

int solution(int A[], int N) {
    // write your code in C99 (gcc 6.2.0)

    //allocate two arrays to hold beginning and ending points of each circle 
    my_type *lower = calloc(N, sizeof(my_type));
    my_type *upper = calloc(N, sizeof(my_type));
    int i;
    my_type count = 0;

    //initialize arrays
    for(i = 0; i < N; i++) {
        lower[i] = i - A[i];
        upper[i] = i + A[i];
    }

    qsort(lower, N, sizeof(my_type), comp);
    qsort(upper, N, sizeof(my_type), comp);

    int open = 0;
    int upper_index = 0;

    for(i = 0; i < N; i++) {
        while(lower[i] > upper[upper_index]) {
            //printf("closing %d\n", upper[upper_index]);
            upper_index++;
            open--;
        }

        open++;
        count += (open-1);

        //printf("opening %d\n", lower[i]);
    }

    free(lower);
    free(upper);

    return ((int)count <= LIMIT) ? (int)count : -1;
}

person Rorschach    schedule 09.03.2020    source источник
comment
Может ли это быть связано с тем, что 2147483647 есть INT_MAX?   -  person Weather Vane    schedule 09.03.2020
comment
@WeatherVane возможно, но я не понимаю, почему, потому что (я думаю) каждый раз, когда я работаю с этим значением, я использую long long int.   -  person Rorschach    schedule 09.03.2020
comment
upper[i] = i + A[i]; Обратите внимание, что сложение будет выполняться как int, а не как long long int, поэтому может произойти переполнение, если A[i] близко к INT_MAX. Может ли это быть проблема?   -  person Nate Eldredge    schedule 09.03.2020


Ответы (1)


Правая сторона этих

lower[i] = i - A[i];
upper[i] = i + A[i];

выполняет int сложение. Вы должны привести один из операндов:

lower[i] = (my_type)i - A[i];
upper[i] = (my_type)i + A[i];

для предотвращения целочисленного переполнения.

person Weather Vane    schedule 09.03.2020
comment
Истинный. Спасибо. Интересно, зачем они создали такого оператора, в котором очень легко ошибиться. - person Rorschach; 09.03.2020
comment
Это было бы нормально, если бы конечный тип был int, а исходные типы — char из-за целочисленных рекламных акций. - person Weather Vane; 09.03.2020