开发者

How do I generate random numbers without rand() function?

I want to generate (pseudo) random numbers between 0 and some integer. I don't mind if they aren't too random. I have access to the current time of the day but not the rand function. Can anyone think of a sufficiently robust way to generate these? Perhap开发者_如何学JAVAs, discarding some bits from time of day and taking modulo my integer or something?

I am using c.


If you're after an ultra-simple pseudo-random generator, you can just use a Linear Feedback shift Register.

The wikipedia article has some code snippets for you to look at, but basically the code for a 16-bit generator will look something like this (lightly massaged from that page...)

  unsigned short lfsr = 0xACE1u;
  unsigned bit;

  unsigned rand()
  {
    bit  = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5) ) & 1;
    return lfsr =  (lfsr >> 1) | (bit << 15);
  }


For "not too random" integers, you could start with the current UNIX time, then use the recursive formula r = ((r * 7621) + 1) % 32768;. The nth random integer between 0 (inclusive) and M (exclusive) would be r % M after the nth iteration.

This is called a linear congruential generator.

The recursion formula is what bzip2 uses to select the pivot in its quicksort implementation. I wouldn't know about other purposes, but it works pretty well for this particular one...


Look at implementing a pseudo-random generator (what's "inside" rand()) of your own, for instance the Mersenne twister is highly-regarded.


#include <chrono>

int get_rand(int lo, int hi) {
    auto moment = std::chrono::steady_clock::now().time_since_epoch().count();
    int num = moment % (hi - lo + 1);
    return num + lo;
}


The only "robust" (not easily predictable) way of doing this is writing your own pseudo-random number generator and seeding it with the current time. Obligatory wikipedia link: http://en.wikipedia.org/wiki/Pseudorandom_number_generator


You can get the "Tiny Mersenne Twister" here: http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/TINYMT/index.html

it is pure c and simple to use. E.g. just using time:

#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));
}


The smallest and simple random generator which work with ranges is provided below with fully working example.

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;
}


If you're not generating your numbers too fast (*1) and your upper limit is low enough (*2) and your "time of day" includes nanoseconds, just use those nanoseconds.

#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;
}

And a sample run ...

please type 769 (< 50 quits): 769
please type 185 (< 50 quits): 185
please type 44 (< 50 quits): 44

(*1) if you're using them interactively, one at a time
(*2) if you want numbers up to about 1000


You can write your own rand() function. Like:

Method 1: Using the Concept of static variable: example code:

int random_number_gen(int min_range, int max_range){
    static int rand_number = 199198; // any random number
    rand_number = ((rand_number * rand_number) / 10 ) % 9890;
    return rand_number % (max_range+1-min_range) + min_range ; 
}

Method 2. Using a random/unique value, for example, the current time in microseconds.

#include<time.h>
#include <chrono>
using namespace std;


uint64_t timeSinceEpochMicrosec() {
    using namespace std::chrono;
    return duration_cast<microseconds>(system_clock::now().time_since_epoch()).count();
}

int random_number_gen(int min_range, int max_range){
    long long int current_time = timeSinceEpochMicrosec();
    int current_time_in_sec = current_time % 10000000; 
    int rand_number = current_time_in_sec % (max_range+1-min_range) + min_range ;
    return rand_number;
}


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());
    }
}

}

This is a random number generator where it is guaranteed that the sequence never repeats itself. I have paired time with object value (randomly put by java) with LFSR.

Advantages:

  • The sequence doesn't repeat itself
  • The sequence is new on every run

Disadvantages:

  • Only compatible with java. In C++, new object that is created is same on every run.
  • But there too time and LFSR parameters would put in enough randomness
  • It is slower than most PRNGs as an object needs to be created everytime a number is needed


#include<time.h>
int main(){
int num;
time_t sec;
sec=time(NULL);
printf("Enter the Range under which you want Random 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");
}
return 0;
}


#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;
}


One of the simplest random number generator which not return allways the same value:

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;
  }  

You can maybe get the time to set the start value if you dont want that the sequence starts always with the same value.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜