Подтвердить что ты не робот

Как генерировать случайные числа без функции rand()?

Я хочу сгенерировать (псевдо) случайные числа между 0 и некоторым целым числом. Я не возражаю, если они не слишком случайны. У меня есть доступ к текущему времени суток, но не функция rand. Может ли кто-нибудь подумать о достаточно надежном способе их создания? Возможно, отбрасывая некоторые бит с момента времени и принимая по модулю мое целое или что-то еще?

Я использую c.

4b9b3361

Ответ 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;
  }  

Возможно, вам понадобится время, чтобы установить начальное значение, если вы не хотите, чтобы последовательность всегда начиналась с того же значения.