codememo

rand() 함수 없이 난수를 생성하려면 어떻게 해야 합니까?

tipmemo 2023. 9. 15. 21:01
반응형

rand() 함수 없이 난수를 생성하려면 어떻게 해야 합니까?

0에서 일부 정수 사이의 난수를 생성하고 싶습니다.너무 무작위적이지 않아도 상관없습니다.저는 현재 시간에는 접근할 수 있지만 란드 함수는 접근할 수 없습니다.이것들을 생성할 수 있는 충분히 강력한 방법을 생각해 낼 수 있는 사람이 있습니까?하루 중에 몇 개의 비트를 버리고 모듈로 정수 같은 것을 가져가는 것은 아닐까요?

저는 c를 사용하고 있습니다.

만약 당신이 초간단 의사 랜덤 생성기를 쫓고 있다면, 선형 피드백 쉬프트 레지스터를 사용하면 됩니다.

위키피디아 기사에는 여러분이 볼만한 코드 조각들이 있지만, 기본적으로 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);
  }

"너무 무작위하지 않은" 정수의 경우, 현재 UNIX 시간으로 시작한 다음 재귀 공식을 사용할 수 있습니다.r = ((r * 7621) + 1) % 32768;. 사이의 n번째 난수 정수0(해적) 및M(단독)일 것입니다.r % Mn번 반복 후에

이를 선형 합동 생성기라고 합니다.

재귀 공식은 bzip2가 퀵소트 구현에서 피벗을 선택하는 데 사용하는 공식입니다.다른 목적은 몰라도 이 특정한 목적에는 꽤 효과가 있어요

의사 랜덤 생성기를 구현하는 방법을 살펴봅니다("내부"에 있는 것").rand()예를 들어 메르센 트위스터는 매우 존경을 받고 있습니다.

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

이를 수행하는 유일한 "강력한"(쉽게 예측할 수 없는) 방법은 자신의 의사 난수 생성기를 작성하고 현재 시간과 함께 시드를 받는 것입니다.필수 위키백과 링크: http://en.wikipedia.org/wiki/Pseudorandom_number_generator

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

범위에서 작동하는 가장 작고 간단한 랜덤 생성기는 완전 작동 예제와 함께 아래에 제공됩니다.

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

숫자를 너무 빨리 생성하지 않고(*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;
}

그리고 샘플 런...

769(< 50 Quit)를 입력하십시오: 769185(< 50 Quit)를 입력하십시오: 18544를 입력하십시오(< 50 Quit): 44

(* 한 으로1) 하는 에 에 으로 하는
(*약* 2 )약 1000를는우의우약

란드() 함수를 직접 작성할 수 있습니다.좋아요:

방법 1: 정적 변수의 개념 사용: 예제 코드:

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

방법 2.현재 시간(마이크로초)과 같이 임의/고유 값을 사용합니다.

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

}

이것은 순서가 반복되지 않는다는 것이 보장되는 난수 생성기입니다.LFSR로 객체 값(자바에서 임의로 입력)과 시간을 페어링했습니다.

장점:

  • 이 순서는 반복되지 않습니다.
  • 시퀀스는 모든 실행 시마다 새 것입니다.

단점:

  • 자바와만 호환됩니다.C++에서 생성되는 새 개체는 실행할 때마다 동일합니다.
  • 하지만 너무 많은 시간과 LFSR 파라미터가 충분한 무작위성을 부여할 것입니다.
  • 숫자가 필요할 때마다 개체를 만들어야 하기 때문에 대부분의 PRNG보다 느립니다.
#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;
}

항상 같은 값을 반환하지 않는 가장 단순한 난수 생성기 중 하나:

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

시퀀스가 항상 동일한 값으로 시작하는 것을 원하지 않는 경우 시작 값을 설정할 시간을 얻을 수 있습니다.

언급URL : https://stackoverflow.com/questions/7602919/how-do-i-generate-random-numbers-without-rand-function

반응형