Модулен оператор срещу нула (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)


Важно е да се отбележи, че тук имаме работа с неподписани int (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 всъщност е допълнение към 2 на upper_bound. Да приемем, че upper_bound=10, тогава -upper_bound е 0xFFFFFFF6=246. След това -upper_bound % upper_bound = 246%10 = 6. И можете да го тествате.

person Eugene Sh.    schedule 28.05.2015