Как генерировать случайные числа без функции rand()?
Я хочу сгенерировать (псевдо) случайные числа между 0 и некоторым целым числом. Я не возражаю, если они не слишком случайны. У меня есть доступ к текущему времени суток, но не функция rand. Может ли кто-нибудь подумать о достаточно надежном способе их создания? Возможно, отбрасывая некоторые бит с момента времени и принимая по модулю мое целое или что-то еще?
Я использую c.
Ответы
Ответ 1
Если вы используете сверхпростой псевдослучайный генератор, вы можете просто использовать Линейный регистр сдвига обратной связи.
В статье wikipedia есть некоторые фрагменты кода, на которые вы можете посмотреть, но в основном код для 16-разрядного генератора будет выглядеть примерно так (слегка массируется с этой страницы...)
unsigned short lfsr = 0xACE1u;
unsigned bit;
unsigned rand()
{
bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5) ) & 1;
return lfsr = (lfsr >> 1) | (bit << 15);
}
Ответ 2
Для "не слишком случайных" целых чисел вы можете начать с текущего времени UNIX, а затем использовать рекурсивную формулу r = ((r * 7621) + 1) % 32768;
. N-е случайное целое число от 0
(включительно) и M
(исключение) после n-й итерации будет r % M
.
Это называется линейным конгруэнтным генератором.
Формула рекурсии - это то, что bzip2 использует для выбора стержня в реализации быстрой сортировки. Я бы не знал о других целях, но он работает очень хорошо для этого конкретного...
Ответ 3
Посмотрите на реализацию псевдослучайного генератора (что "внутри" rand()
), например Mersenne twister -regarded.
Ответ 4
Единственный "надежный" (нелегко предсказуемый) способ сделать это - написать свой собственный генератор псевдослучайных чисел и посеять его с текущим временем. Обязательная ссылка на wikipedia: http://en.wikipedia.org/wiki/Pseudorandom_number_generator
Ответ 5
Вы можете получить "Tiny Mersenne Twister" здесь: http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/TINYMT/index.html
он чист и прост в использовании. Например. просто используя время:
#include "tinymt32.h"
// And if you can't link:
#include "tinymt32.c"
#include <time.h>
#include <stdio.h>
int main(int argc, const char* argv[])
{
tinymt32_t state;
uint32_t seed = time(0);
tinymt32_init(&state, seed);
for (int i=0; i<10; i++)
printf("random number %d: %u\n", i, (unsigned int)tinymt32_generate_uint32(&state));
}
Ответ 6
Самый маленький и простой случайный генератор, работающий с диапазонами, приведен ниже с полным рабочим примером.
unsigned int MyRand(unsigned int start_range,unsigned int end_range)
{
static unsigned int rand = 0xACE1U; /* Any nonzero start state will work. */
/*check for valid range.*/
if(start_range == end_range) {
return start_range;
}
/*get the random in end-range.*/
rand += 0x3AD;
rand %= end_range;
/*get the random in start-range.*/
while(rand < start_range){
rand = rand + end_range - start_range;
}
return rand;
}
int main(void)
{
int i;
for (i = 0; i < 0xFF; i++)
{
printf("%u\t",MyRand(10,20));
}
return 0;
}
Ответ 7
Если вы не генерируете свои числа слишком быстро (* 1) и ваш верхний предел достаточно низок (* 2), а ваше "время суток" включает наносекунды, просто используйте эти наносекунды.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int nanorand(void) {
struct timespec p[1];
clock_gettime(CLOCK_MONOTONIC, p);
return p->tv_nsec % 1000;
}
int main(void) {
int r, x;
for (;;) {
r = nanorand();
do {
printf("please type %d (< 50 quits): ", r);
fflush(stdout);
if (scanf("%d", &x) != 1) exit(EXIT_FAILURE);
} while (x != r);
if (r < 50) break;
}
puts("");
return 0;
}
И образец запуска...
please type 769 (< 50 quits): 769
please type 185 (< 50 quits): 185
please type 44 (< 50 quits): 44
(* 1) если вы используете их в интерактивном режиме, по одному
(* 2), если вы хотите, чтобы номера до 1000
Ответ 8
import java.io.*;
public class random{
public static class p{
}
static long reg=0;
static long lfsr()
{
if(reg==0)
{
reg=145896027340307l;
}
long bit=(reg>>0^reg>>2^reg>>3^reg>>5)&1;
reg=reg>>1|bit<<62;
return reg;
}
static long getRand()
{
String s=String.valueOf(new p());
//System.out.println(s);
long n=0;
lfsr();
for(int i=0;i<s.length();i++)
{
n=n<<8|+s.charAt(i);
}
System.out.print(n+" "+System.currentTimeMillis()+" "+reg+" ");
n=n^System.currentTimeMillis()^reg;
return n;
}
public static void main(String args[])throws IOException
{
for(int i=0;i<400;i++)
{
System.out.println(getRand());
}
}
}
Это генератор случайных чисел, где гарантируется, что последовательность никогда не повторяется. Я связал время со значением объекта (случайно поставленным Java) с LFSR.
Преимущества:
- Последовательность не повторяется
- Последовательность является новой при каждом запуске
Недостатки:
- Совместимо только с Java. В C++ новый созданный объект одинаков при каждом запуске.
- Но там тоже время и параметры LFSR поместили бы в достаточно случайность
- Это медленнее, чем большинство PRNG, поскольку объект должен создаваться каждый раз, когда требуется число
Ответ 9
Ниже генерируется случайное число, не используя rand fuction
#include<stdio.h>
#include<time.h>
int main()
{
int num;
time_t sec;
sec=time(NULL);
printf("Enter The Number\n");
scanf("%d",&num);
if(num>0)
{
for(;;)
{
sec=sec%3600;
if(num>=sec)
{
printf("%ld\n",sec);
break;
}
sec=sec%num;
}
}
else
{
printf("Please Enter Positive Value\n\n\n*****Thanks For Visit*****\n\n\n");
}
return 0;
}
Может быть, это полезно
Ответ 10
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
int main()
{
unsigned int x,r,i;
// no of random no you want to generate
scanf("%d",&x);
// put the range of random no
scanf("%d",&r);
unsigned int *a=(unsigned int*)malloc(sizeof(unsigned int)*x);
for(i=0;i<x;i++)
printf("%d ",(a[i]%r)+1);
free(a);
getch();
return 0;
}
Ответ 11
Один из простейших генераторов случайных чисел, которые не возвращают всегда одинаковое значение:
uint16_t simpleRand(void)
{
static uint16_t r = 5531; //dont realy care about start value
r+=941; //this value must be relative prime to 2^16, so we use all values
return r;
}
Возможно, вам понадобится время, чтобы установить начальное значение, если вы не хотите, чтобы последовательность всегда начиналась с того же значения.