如何在没有rand()函数的情况下生成随机数?

时间:2011-09-29 20:17:07

标签: c random

我想生成介于0和某个整数之间的(伪)随机数。我不介意他们是不是太随机了。我可以访问当天的当前时间,但不能访问rand功能。任何人都可以想到一种足够强大的方法来生成这些吗?也许,从一天中的某个时间丢弃一些位并以模数形式取整数?

我正在使用c。

12 个答案:

答案 0 :(得分:27)

如果您使用的是超简单的伪随机生成器,则可以使用Linear Feedback shift Register

维基百科文章有一些代码片段供您查看,但基本上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);
  }

答案 1 :(得分:10)

对于“不太随机”的整数,您可以从当前的UNIX时间开始,然后使用递归公式r = ((r * 7621) + 1) % 32768;。在第n次迭代之后,0(包括)和M(不包括)之间的第n个随机整数将是r % M

这称为线性同余发生器。

递归公式是 bzip2 用于在其快速排序实现中选择枢轴的内容。我不知道其他目的,但它适用于这个特别的...

答案 2 :(得分:7)

看看你自己实现了一个伪随机生成器(什么是“内部”rand()),例如Mersenne twister被高度重视。

答案 3 :(得分:0)

唯一“强大”(不易预测)的方法是编写自己的伪随机数生成器并使用当前时间播种它。必须的维基百科链接:http://en.wikipedia.org/wiki/Pseudorandom_number_generator

答案 4 :(得分:0)

你可以在这里找到“Tiny Mersenne Twister”:http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/TINYMT/index.html

纯c,使用简单。例如。只是使用时间:

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

答案 5 :(得分:0)

下面提供了可正常运行的示例,它是最小且简单的随机生成器,它可用于范围

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

答案 6 :(得分:0)

如果您生成数字的速度不是太快(* 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

答案 7 :(得分:0)

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

答案 8 :(得分:-1)

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 :(得分:-1)

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

答案 10 :(得分:-2)

#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 :(得分:-2)

最简单的随机数生成器之一,它不会返回相同的值:

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

如果您不希望序列始终以相同的值启动,您可以花时间设置起始值。

相关问题