rand-31
Вот адаптация вашей программы, в которой более подробно показано, что происходит:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
int x = ((unsigned int)time(NULL));
srand((unsigned int)x);
int r1 = rand();
int y = ((double)r1/(double)(RAND_MAX)*10);
int r2 = rand();
int z = ((double)r2/(double)(RAND_MAX)*10);
printf("Time %d\n", x);
printf("Random 1: %d\n", r1);
printf("Number y: %d\n", y);
printf("Random 2: %d\n", r2);
printf("Number z: %d\n", z);
return 0;
}
Он фиксирует результат двух rand()
вызовов независимо от вычислений, чтобы их можно было распечатать. Это также гарантирует, что значение, переданное в time()
, совпадает с напечатанным значением, хотя шансы, что они будут разными, довольно малы.
Когда я запустил его несколько раз, я получил следующие результаты:
Time 1508694677
Random 1: 1292016210
Number y: 6
Random 2: 1709286653
Number z: 7
Time 1508694685
Random 1: 1292150666
Number y: 6
Random 2: 1821604998
Number z: 8
Time 1508694701
Random 1: 1292419578
Number y: 6
Random 2: 2046241688
Number z: 9
Time 1508694841
Random 1: 1294772558
Number y: 6
Random 2: 790587255
Number z: 3
Как видите, значения, возвращаемые rand()
, разные, но не сильно отличаются, и, следовательно, вычисленное значение не сильно отличается.
rand-23
Один простой вариант обновления - использовать функции drand48()
, например:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
int x = ((unsigned int)time(NULL));
srand48((unsigned int)x);
int r1 = lrand48();
int y = ((double)r1/(double)(RAND_MAX)*10);
int r2 = lrand48();
int z = ((double)r2/(double)(RAND_MAX)*10);
printf("RAND_MAX: %d\n", RAND_MAX);
printf("Time: %d\n", x);
printf("Random 1: %d\n", r1);
printf("Number y: %d\n", y);
printf("Random 2: %d\n", r2);
printf("Number z: %d\n", z);
return 0;
}
Код печатает RAND_MAX
в основном для того, чтобы показать, что он совместим с диапазоном значений, возвращаемым lrand48()
, который задокументирован для возврата значения в диапазоне 0..2 31 -1.
Это дает разные и, возможно, лучшие результаты:
RAND_MAX: 2147483647
Time: 1508695069
Random 1: 705270938
Number y: 3
Random 2: 1758232243
Number z: 8
RAND_MAX: 2147483647
Time: 1508695074
Random 1: 1465504939
Number y: 6
Random 2: 733780153
Number z: 3
RAND_MAX: 2147483647
Time: 1508695080
Random 1: 1948289010
Number y: 9
Random 2: 1222424564
Number z: 5
rand-13
В качестве альтернативы вы можете сделать то, что указано в документации macOS, и переключиться на _ 14_. Ссылка ведет на «устаревшую» документацию XCode 5, но функциональность в последнее время не менялась.
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
int x = ((unsigned int)time(NULL));
int r1 = arc4random_uniform(INT_MAX);
int y = ((double)r1/(double)(RAND_MAX)*10);
int r2 = arc4random_uniform(INT_MAX);
int z = ((double)r2/(double)(RAND_MAX)*10);
printf("INT_MAX: %d\n", INT_MAX);
printf("RAND_MAX: %d\n", RAND_MAX);
printf("Time: %d\n", x);
printf("Random 1: %d\n", r1);
printf("Number y: %d\n", y);
printf("Random 2: %d\n", r2);
printf("Number z: %d\n", z);
return 0;
}
Он использует arc4random_uniform()
для генерации значения в диапазоне 0..INT_MAX, в том же диапазоне, что и другие сгенерированные функции. Аналога srand()
с семейством функций arc4random()
не существует.
Примеры прогонов:
INT_MAX: 2147483647
RAND_MAX: 2147483647
Time: 1508695894
Random 1: 938614006
Number y: 4
Random 2: 851262647
Number z: 3
INT_MAX: 2147483647
RAND_MAX: 2147483647
Time: 1508695900
Random 1: 1332829945
Number y: 6
Random 2: 386007903
Number z: 1
INT_MAX: 2147483647
RAND_MAX: 2147483647
Time: 1508695913
Random 1: 1953583540
Number y: 9
Random 2: 1273643162
Number z: 5
rand-83
Обратите внимание: если вам нужно случайное целое число от 0 до 10, вам следует использовать arc4random_uniform(10)
напрямую, а не выполнять вычисления.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
int x = ((unsigned int)time(NULL));
int y = arc4random_uniform(10);
int z = arc4random_uniform(10);
printf("Time: %d\n", x);
printf("Number y: %d\n", y);
printf("Number z: %d\n", z);
return 0;
}
Примеры результатов:
Time: 1508696162
Number y: 5
Number z: 3
Time: 1508696163
Number y: 7
Number z: 5
Time: 1508696165
Number y: 3
Number z: 8
Еще одно преимущество arc4random()
и др. Проявилось, когда мне удалось запустить программу 3 раза за одну секунду. С другими генераторами они дали бы те же результаты из-за использования того же начального числа.
$ rand-83;rand-83;rand-83
Time: 1508696213
Number y: 4
Number z: 0
Time: 1508696213
Number y: 0
Number z: 1
Time: 1508696213
Number y: 9
Number z: 6
$
$ rand-31;rand-31;rand-31
Time 1508696334
Random 1: 1319865409
Number y: 6
Random 2: 1619339200
Number z: 7
Time 1508696334
Random 1: 1319865409
Number y: 6
Random 2: 1619339200
Number z: 7
Time 1508696334
Random 1: 1319865409
Number y: 6
Random 2: 1619339200
Number z: 7
$
JFTR: код, скомпилированный на MacBook Pro под управлением macOS High Sierra 10.13. Я использовал GCC 7.2.0 (а не XCode 9) для компиляции, но системную библиотеку - и это библиотека, которая здесь критична.
person
Jonathan Leffler
schedule
22.10.2017
time
(начальное значение) медленно увеличивается и делится на большое число, поэтому частное не будет отличаться до тех пор, пока не пройдет более длительное время. Второй вызовrand
производит значение, совершенно отличное от начального. - person Weather Vane   schedule 22.10.20177
вместо5
. Я ожидаю, что7
в конечном итоге вырастет до8
. - person Weather Vane   schedule 22.10.20175
на OS X / XCode. - person Stephan Lechner   schedule 22.10.2017man 3 rand
) указано, что интерфейс rand устарел и его следует заменить на arc4random (3) (например, перейти на терминал и ввестиman 3 arc4random
, чтобы получить документацию). - person James Snook   schedule 22.10.2017rand
, которая может вычислить новое значение и вернуть его или вернуть текущее значение после вычисления следующего значения. В последнем случае начальное значение будет возвращено при первом вызовеrand
. P.S. в моем тесте7
теперь продвинулся до8
. - person Weather Vane   schedule 22.10.2017time()
дважды; существует вероятность его изменения между двумя вызовами. Еслиx
предназначен для хранения значения, используемого в качестве начального числа, лучше назначитьx
, а затем использовать x как начальное значение. - person Clifford   schedule 22.10.2017x = ((unsigned int)time(NULL));
присваивает 'unsigned int' 'int'. Функция неявного преобразования C может вас спасти (но компилятор выдаст предупреждающее сообщение.) - person user3629249   schedule 23.10.2017(double)(RAND_MAX)*10)
пытается умножить2147483647
(максимальное положительное целое число со знаком) на 10. Это приведет к переполнению числа со знаком. Умножение двойного на целое число приводит к неявному преобразованию, выполняемому компилятором. Это заставит компилятор вывести предупреждающее сообщение. Кроме того, присвоениеint
изdouble
заставит компилятор вывести предупреждающее сообщение. При компиляции всегда включайте предупреждения, а затем исправляйте эти предупреждения. - person user3629249   schedule 23.10.2017