уточнение для RAND_MAX и rand() в c stdlib.h

почему следующий код c создает действительные числа только в диапазоне от 0 до 1 (например: 0,840188,0,394383... и т. д.) для double a,b, когда значение для RAND_MAX выглядит как 0.000000 . Разве RAND_MAX не должно устанавливать максимальное значение для числа, сгенерированного функцией rand()?

    #include <stdio.h>
    #include <stdlib.h>
    int main()
    {

    double a,b,c;
    for (int i=0;i<100;i++){
    a=(double)rand()/(double)RAND_MAX;
    b=(double)rand()/(double)RAND_MAX;
    c=a-b;
    printf("itteration : %d values a=%f,b=%f,c=%f, RAND_MAX=%f \n",i,a,b,c,RAND_MAX);
    }  
    return 0;
    }

person TheSprintingEngineer    schedule 28.08.2018    source источник
comment
если x находится между 0 и max, результат x/max всегда будет между 0 и 1 этой простой математикой. Кроме того, RAND_MAX не является двойным, это целое число, поэтому используйте %d для его печати с помощью printf. rand не подходит для генерации двойного числа, это дизайн для целого числа, и он не очень случайный. Вы должны искать библиотеку, которая обрабатывает случайные числа в C.   -  person Stargateur    schedule 28.08.2018
comment
исх. также: Почему printf(%f,0); дать неопределенное поведение?   -  person Sander De Dycker    schedule 28.08.2018


Ответы (2)


RAND_MAX - это интегральная константа, но вы печатаете ее с помощью спецификатора %f (используется для double), что является неопределенным поведением (и в вашем случае происходит печать 0). Используйте %d, и вы увидите фактическое значение RAND_MAX.

Между прочим, почти любой приличный компилятор предупредит вас об этом недействительном printf, если вы выставите предупреждения достаточно высоко. Обязательно сделайте это, C и C++ полны ловушек, по крайней мере, позвольте компилятору помочь вам, когда он может.

person Matteo Italia    schedule 28.08.2018
comment
ах да спасибо! но быстрый взгляд на исходный код показывает #define RAND_MAX 2147483647, но RAND_MAX не определяется как целое число, а является непосредственным значением без типа. принимает ли компилятор немедленное значение и присваивает его как целочисленный тип по умолчанию? - person TheSprintingEngineer; 03.09.2018
comment
@TheSprintingEngineer a #define создает макрос, который представляет собой жестокую текстовую замену, поэтому всякий раз, когда вы пишете RAND_MAX, это точно так же, как если бы вы писали 2147483647; теперь это значение представляет собой десятичный целочисленный литерал, поскольку оно соответствует соответствующему произведению грамматики, то есть [1-9][0-9]*. Тип десятичных целочисленных выражений определяется с помощью алгоритма, подробно описанного в стандарте, который, по сути, выглядит так: взять проанализированное число и попытаться вписать его в int, unsigned int, long, unsigned long, long long, unsigned long long; первое, что может его представить, это его тип. - person Matteo Italia; 03.09.2018
comment
Кстати, интересно отметить, что стандарт требует, чтобы RAND_MAX было просто константным интегральным выражением, которое не налагает никаких ограничений на свой конкретный целочисленный тип, поэтому теоретически реализация может иметь #define RAND_MAX 32767ULL (то есть литерал unsigned long long) ; следовательно, для максимальной переносимости при печати его следует сначала привести к int, в противном случае спецификатор %d может быть неверным (OTOH, нет риска переполнения при приведении, поскольку RAND_MAX — это максимальное значение, которое может вернуть rand(), и он возвращает int, значит точно должно подойти). - person Matteo Italia; 03.09.2018

... значение для RAND_MAX выглядит равным 0,000000.

Вы печатаете целое число, используя спецификатор для двойного числа. Это неопределенное поведение.

Из стандарта C99 (N1256).

7.19.6.3 Функция printf
...
2. Функция printf эквивалентна fprintf с аргументом stdout, вставленным перед аргументами функции printf.

7.19.6.1 Функция fprintf
....
9. Если спецификация преобразования недействительна, поведение не определено. Если какой-либо аргумент не соответствует типу соответствующей спецификации преобразования, поведение не определено.

Итак, он печатает 0.000 вместо RAND_MAX. Ваш другой вопрос:

Разве RAND_MAX не должен устанавливать максимальное значение для числа, сгенерированного функцией rand()?

rand() возвращает псевдослучайное число в диапазоне от 0 до RAND_MAX. RAND_MAX — это константа, значение которой по умолчанию может варьироваться в зависимости от реализации, но должно быть не менее 32767.

Но деление с плавающей запятой rand() на RAND_MAX даст значение от 0 до 1.

person P.W    schedule 28.08.2018