Objective C: предвзятость По модулю

В1) Ваша версия atoi() слишком проста, стандартная версия игнорирует начальные пробельные символы и обрабатывает необязательный знак перед числом. atoi(" -123junk") следует оценить до -123.

Q2) atoi - это стандартная функция, определенная прототипом int atoi(const char *s);, она возвращает целое число.

В3) В Code 2 есть несколько ошибок:

  • вы указываете размер массива char s как i, который неинициализирован. вместо этого вы должны определить массив с достаточно большим значением, таким как 64,
  • , вы должны проверить на потенциальное переполнение буфера в цикле,
  • вы должны проверить для EOF, чтобы остановить цикл в случае, если конец файла встречается без перевода строки.

Вот модифицированная версия:

#include <stdio.h>
#include <stdlib.h>

int main() {
    char s[64];
    size_t i;
    int c;
    for (i = 0; i < sizeof(s) - 1 && (c = getchar()) != EOF;) {
       s[i++] = c;
       if (c == '\n')
           break;
    }
    s[i] = '\0';
    printf("%i", atoi(s));
    return 0;
}

Q4) выражение n = 10 * n + (s[i] - '0') вычисляется для каждой новой цифры, найденной в строке. Действительно, немного неэффективно умножать текущее значение на 10 до тех пор, пока не будет найдено ненулевой цифры, но написать функцию таким образом просто.

Чтобы избежать этих бесполезных умножений, вот альтернатива:

int atoi(const char *s) {
    int n = 0;
    size_t i = 0;

    while (s[i] == '0')
        i++;
    if (s[i] >= '1' && s[i] <= '9') {
        n = s[i++] - '0';
        while (s[i] >= '0' && s[i] <= '9')
            n = 10 * n + (s[i++] - '0');
    }
    return n;
}

Но эта функция более громоздка и может фактически быть менее эффективной, чем простая версия. Попробуйте и сравните тесты в вашей системе.

Для полноты, вот полная переносимая версия, использующая ctype.h>, которая обрабатывает необязательный начальный пробел и необязательный знак. Он также обрабатывает переполнение с определенным поведением, хотя для этого не требуется стандартная версия atoi().

#include <limits.h>
#include <stdio.h>

int atoi(const char *s) {
    int n = 0, d;

    /* skip optional initial white space */
    while (isspace((unsigned char)*s))
        s++;
    if (*s == '-') {
        /* convert negative number */
        s++;
        while (isdigit((unsigned char)*s)) {
            d = (*s++ - '0');
            /* check for potential arithmetic overflow */
            if (n < INT_MIN / 10 || (n == INT_MIN / 10 && -d < INT_MIN % 10)) {
                n = INT_MIN;
                break;
            }
            n = n * 10 - d;
        }
    } else {
        /* ignore optional positive sign */
        if (*s == '+')
            s++;
        while (isdigit((unsigned char)*s)) {
            d = (*s++ - '0');
            /* check for potential arithmetic overflow */
            if (n > INT_MAX / 10 || (n == INT_MAX / 10 && d > INT_MAX % 10)) {
                n = INT_MAX;
                break;
            }
            n = n * 10 + d;
        }
    }
    return n;
}

int main(int argc, char *argv[]) {
    int i, n;

    for (i = 1; i < argc; i++) {
        n = atoi(argv[i]);
        printf("\"%s\" -> %d\n", argv[i], n);
    }
    return 0;
}
13
задан Cœur 5 February 2019 в 14:04
поделиться

3 ответа

arc4random возвращает 32-разрядное целое число без знака (от 0 до 2 <глоток> 32 -1).

, вероятно, не будет никакой noticable предвзятости по модулю для достаточно маленького x. Однако, если Вы хотите быть действительно уверенными, сделайте это:

год = 2 <глоток> p , где 2 <глоток> p-1 < x в‰ 2¤ <глоток> p

val = arc4random() % y;
while(val >= x)
    val = arc4random() % y;
14
ответ дан 1 December 2019 в 17:16
поделиться
u_int32_t maxValue = ~((u_int32_t) 0);      // equal to 0xffff...
maxValue -= maxValue % x;                   // make maxValue a multiple of x
while((value = arc4random()) >= maxValue) { // loop until we get 0 ≤ value < maxValue
}
value %= x;

, хотя, если Вы не используете x менее чем миллион (или больше) я не волновался бы об этом

4
ответ дан 1 December 2019 в 17:16
поделиться

Если максимальное значение arc4random модификация x больше, чем x, проигнорируйте любые значения, больше, чем самое большое arc4random-max mod x, звоня arc4random снова вместо этого.

2
ответ дан 1 December 2019 в 17:16
поделиться