Модульный оператор против нуля (re: источник arc4random_uniform)

Я обнаружил, что смотрю на источник arc4random_uniform (http://bxr.su/o/lib/libc/crypt/arc4random_uniform.c)

Мой вопрос относится к следующей строке (комментарий является их оригинальным комментарием):

/* 2**32 % x == (2**32 - x) % x */
min = -upper_bound % upper_bound;

Я не гений математики, но, конечно же, -N%N всегда будет равно нулю. Так почему бы просто не написать

min=0

person Little Code    schedule 28.05.2015    source источник
comment
Связано: stackoverflow. com/questions/8026694/   -  person dragosht    schedule 28.05.2015


Ответы (2)


Важно отметить, что здесь мы имеем дело с беззнаковыми целыми числами (uint32_t), поэтому -upper_bound не делает того, что вы думаете. На самом деле это 2**32 - upper_bound из-за переноса по модулю, и цель этого объясняется в комментарии выше (т.е. получение 2**32 % upper_bound без переполнения).

Пример:

#include <stdio.h>
#include <stdint.h>

int main()
{
    uint32_t upper_bound = 42;
    uint32_t min = -upper_bound % upper_bound;
    printf("%u -> %u\n", upper_bound, min);
    return 0;
}

дает:

42 -> 4

АКТИВНЫЙ КОД

person Paul R    schedule 28.05.2015

Во-первых, стоит упомянуть, что переменные uint32_t, то есть беззнаковые. Тогда давайте посмотрим внимательно: -upper_bound % upper_bound = (-upper_bound) % upper_bound;. Это означает, что -upper_bound на самом деле является дополнением upper_bound до 2. Предположим, что upper_bound=10, тогда -upper_bound равно 0xFFFFFFF6=246. Затем -upper_bound % upper_bound = 246%10 = 6. И вы можете протестировать его.

person Eugene Sh.    schedule 28.05.2015