난수 생성


271

C ++에서 임의의 부동 소수점을 어떻게 생성합니까?

정수 랜드를 가져 와서 무언가로 나눌 수 있다고 생각했는데 충분합니까?


2
그것은 당신이 원하는 숫자와 무작위에 달려 있습니다. 일반적으로 rand ()는 15 비트의 임의성을 제공하지만 float의 정밀도는 23 비트이므로 일부 값이 누락됩니다.
Pete Kirkham

1
사용 가능한 모든 주요 옵션을 포함하도록 내 대답을 업데이트 random했으며 C ++ 11에 추가 된 헤더 에 중점을 둔 선택 은 표준 문서 N3924 : C ++ 14의 rand () 방해로 더 강화되었습니다 . 나는 rand()주로 역사적 고려 사항에 대한 답변에 포함 하지만 레거시 응용 프로그램이 존재한다는 것을 깨닫습니다.
Shafik Yaghmour 2014 년

내 대답은 <random>헤더로 매번 같은 숫자를 피하는 방법을 포함합니다
Andreas DM

답변:


381

rand()C ++에서 의사 난수를 생성하는 데 사용할 수 있습니다. RAND_MAX약간의 수학과 함께 사용 하면 원하는 임의의 간격으로 난수를 생성 할 수 있습니다. 학습 목적과 장난감 프로그램에 충분합니다. 정규 분포를 사용하여 실제로 임의의 숫자가 필요한 경우 더 고급 방법을 사용해야합니다.


0.0부터 1.0까지의 숫자가 생성됩니다.

float r = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);

이것은 어떤 임의 0.0의 숫자를 생성 할 것이다 float, X:

float r2 = static_cast <float> (rand()) / (static_cast <float> (RAND_MAX/X));

이것은 어떤 임의의 숫자가 생성됩니다 LO어떤 임의의로를 HI:

float r3 = LO + static_cast <float> (rand()) /( static_cast <float> (RAND_MAX/(HI-LO)));

점을 유의 rand()당신이 진정으로 임의의 숫자를 필요로하는 경우 함수가 종종 충분하지 않을 것입니다.


전화하기 전에 먼저을 호출 rand()하여 난수 생성기를 "시드"해야합니다 srand(). 전화를 걸 때마다 한 번이 아니라 프로그램 실행 중에 한 번 수행해야합니다 rand(). 이것은 종종 다음과 같이 수행됩니다 :

srand (static_cast <unsigned> (time(0)));

전화를 걸 rand거나 srand해야합니다 #include <cstdlib>.

전화 time를하려면 다음을 수행해야합니다 #include <ctime>.


22
먼저 씨를 뿌리는 것을 잊지 마십시오!
Klaim

14
두 한계가 모두 포함되어 있습니다.
dmckee --- 전 운영자 고양이

14
이 답변은 잘못된 것입니다. 지난주 Going Native 2013에서 다루었 다. rand () 매우 자세한 설명은 channel9.msdn.com/Events/GoingNative/2013/… 을 고려 하십시오 .
Ade Miller

14
왜 그렇게 많은 사람들이이 답변을 찬성했는지 이해하지 못합니다. 수학적으로 올바르지 않습니다. RAND_MAX는 매우 작은 숫자입니다 (일반적으로 2 ^ 16). 즉, 23 비트의 부동 소수점에서 15 개만 무작위로 만듭니다. 다른 것들은 아마도 0 일 것입니다. 균일 분포에서는 정밀도가 낮은 난수를 얻을 수 있습니다. 예를 들어 랜덤 생성기는 0.00001 및 0.00002를 생성 할 수 있지만 0.000017을 생성 할 수는 없습니다. 따라서 분포는 균일하지만 정밀도는 낮습니다 (실제 부동 소수점보다 정밀도가 256 배 낮음).
DanielHsH

10
@DanielHsH : OP는와 함께 임의의 실수를 생성하기 위해 어떤 역학을 사용할 수 있는지 구체적으로 물었습니다 rand(). 이 질문과 나의 대답은 구체적으로 기초를 배우는 데 중점을 두 었으며 높은 정밀도에 대해서는 신경 쓰지 않았습니다. 달리기를 배우기 전에 걷는 법을 배워야합니다.
John Dibling

137

C ++ 11은로 많은 새로운 옵션을 제공 random합니다. 이 주제에 대한 표준 논문 은 C ++ 11의 난수 생성 N3551입니다.

사용 rand()이 왜 문제가 될 수 있는지 알아 보려면 GoingNative 2013 행사 에서 제공된 Stephan T. Lavavejrand () 고려 된 유해 프레젠테이션 자료를 참조하십시오 . 슬라이드는 주석에 있지만 여기에 직접 링크가 있습니다.

레거시 코드는 여전히 지원이 필요할 수 있으므로 boost사용뿐만 아니라 다루고 rand있습니다.

아래 예제는 cppreference 사이트에서 추출한 std :: mersenne_twister_engine 엔진 및 std :: uniform_real_distribution 을 사용하여 [0,10)간격 에 따라 숫자를 생성 하고 다른 엔진 및 분배는 주석 처리됩니다 ( 실제 참조 ).

#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <random>

int main()
{
    std::random_device rd;

    //
    // Engines 
    //
    std::mt19937 e2(rd());
    //std::knuth_b e2(rd());
    //std::default_random_engine e2(rd()) ;

    //
    // Distribtuions
    //
    std::uniform_real_distribution<> dist(0, 10);
    //std::normal_distribution<> dist(2, 2);
    //std::student_t_distribution<> dist(5);
    //std::poisson_distribution<> dist(2);
    //std::extreme_value_distribution<> dist(0,2);

    std::map<int, int> hist;
    for (int n = 0; n < 10000; ++n) {
        ++hist[std::floor(dist(e2))];
    }

    for (auto p : hist) {
        std::cout << std::fixed << std::setprecision(1) << std::setw(2)
                  << p.first << ' ' << std::string(p.second/200, '*') << '\n';
    }
}

출력은 다음과 유사합니다.

0 ****
1 ****
2 ****
3 ****
4 *****
5 ****
6 *****
7 ****
8 *****
9 ****

우리가 가기로 결정하면 출력 그래서, 어떤 당신이 선택하는 분포에 따라 달라집니다 표준 : normal_distribution 의 값이 2모두 평균STDDEV 예를 들어, dist(2, 2)대신 출력이 유사하다 ( 이 살고 참조 )

-6 
-5 
-4 
-3 
-2 **
-1 ****
 0 *******
 1 *********
 2 *********
 3 *******
 4 ****
 5 **
 6 
 7 
 8 
 9 

다음은 제시된 일부 코드의 수정 된 버전입니다 N3551( 실제 참조 ).

#include <algorithm>
#include <array>
#include <iostream>
#include <random>

std::default_random_engine & global_urng( )
{
    static std::default_random_engine u{};
    return u ;
}

void randomize( )
{
    static std::random_device rd{};
    global_urng().seed( rd() );
}

int main( )
{
  // Manufacture a deck of cards:
  using card = int;
  std::array<card,52> deck{};
  std::iota(deck.begin(), deck.end(), 0);

  randomize( ) ;  

  std::shuffle(deck.begin(), deck.end(), global_urng());
  // Display each card in the shuffled deck:
  auto suit = []( card c ) { return "SHDC"[c / 13]; };
  auto rank = []( card c ) { return "AKQJT98765432"[c % 13]; };

  for( card c : deck )
      std::cout << ' ' << rank(c) << suit(c);

   std::cout << std::endl;
}

결과는 다음과 유사합니다.

5H 5S AS 9S 4D 6H TH 6D KH 2S QS 9H 8H 3D KC TD 7H 2D KS 3C TC 7D 4C QH QC QD JD AH JC AC KD 9D 5C 2H 4H 9C 8C JH 5D 4S 7C AD 3S 8S TS 2C 8D 3H 6C JS 7S 6S

후원

물론 Boost.Random 은 항상 옵션입니다. 여기서 boost :: random :: uniform_real_distribution을 사용하고 있습니다 .

#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_real_distribution.hpp>

int main()
{
    boost::random::mt19937 gen;
    boost::random::uniform_real_distribution<> dist(0, 10);

    std::map<int, int> hist;
    for (int n = 0; n < 10000; ++n) {
        ++hist[std::floor(dist(gen))];
    }

    for (auto p : hist) {
        std::cout << std::fixed << std::setprecision(1) << std::setw(2)
                  << p.first << ' ' << std::string(p.second/200, '*') << '\n';
    }
}

랜드()

사용해야하는 경우 부동 소수점 난수를 생성하는 방법 에 대한 지침 rand()C FAQ 를 참조하십시오 . 기본적으로 간격을 생성하기 위해 이와 유사한 예제를 제공합니다 [0,1).

#include <stdlib.h>

double randZeroToOne()
{
    return rand() / (RAND_MAX + 1.);
}

다음 범위에서 임의의 숫자를 생성합니다 [M,N).

double randMToN(double M, double N)
{
    return M + (rand() / ( RAND_MAX / (N-M) ) ) ;  
}

1
randMToNpls 를 고칠 수 있습니까? 하나 그건 참고 [M,N]하거나 다시 추가 + 1.위에서 randZeroToOne. -> 이렇게 부르는 것을 생각하십시오 :randMToN(0.0, 1.0);
BeyelerStudios

1
에서 0으로 나누는 것도주의하십시오 (N-M). 이 오류를 처리하는 좋은 방법은 다음과 같습니다. stackoverflow.com/questions/33058848/…
Dr Beco

61

Boost.Random을 살펴보십시오 . 다음과 같이 할 수 있습니다.

float gen_random_float(float min, float max)
{
    boost::mt19937 rng;
    boost::uniform_real<float> u(min, max);
    boost::variate_generator<boost::mt19937&, boost::uniform_real<float> > gen(rng, u);
    return gen();
}

매번 새로운 객체를 생성하는 대신 동일한 mt19937 객체를 전달하는 것이 좋습니다.하지만 아이디어를 얻길 바랍니다.


1
uniform_real은 반 개방 간격 [최소, 최대]을 사용하므로 최소값을 얻지 만 절대 최대 값에 도달하지는 않습니다. 어떤 식 으로든 반올림하면이 문제를 극복 할 수는 있지만 고려해야 할 사항입니다.
TehWan

20
이것은 이제 C ++ 11의 일부입니다.
Tomas Andrle

@Wolf 실제 응용 프로그램에서 특정 부동 소수점 값을 칠 확률은 너무 낮아 엔드 포인트가 포함되거나 제외되는지는 중요하지 않습니다. 당신이 필요로하는 경우 max그러나이 개방형 사용할 수 있습니다 min, 당신은 쉽게 간격을 반전 할 수 있습니다 return min + max - gen();.
Mark Ransom

26

현대에서는 함께 제공 c++되는 <random>헤더를 사용할 수 있습니다 c++11.
무작위를 얻으려면 float사용할 수 있습니다 std::uniform_real_distribution<>.

함수를 사용하여 숫자를 생성 할 수 있으며 숫자가 항상 동일하지 않게 하려면 엔진과 분포를로 설정하십시오 static.
예:

float get_random()
{
    static std::default_random_engine e;
    static std::uniform_real_distribution<> dis(0, 1); // rage 0 - 1
    return dis(e);
}

float의 컨테이너를 다음과 같은 컨테이너에 배치하는 것이 이상적입니다 std::vector.

int main()
{
    std::vector<float> nums;
    for (int i{}; i != 5; ++i) // Generate 5 random floats
        nums.emplace_back(get_random());

    for (const auto& i : nums) std::cout << i << " ";
}

출력 예 :

0.0518757 0.969106 0.0985112 0.0895674 0.895542

std::uniform_real_distribution<> dis(0, 1); // rage 0 - 1기술적으로 잘못되었습니다. 1.0은 생성되지 않습니다. en.cppreference.com/w/cpp/numeric/random/… To create a distribution over the closed interval [a,b], std::nextafter(b, std::numeric_limits<RealType>::max()) may be used as the second parameter.
Troyseph

1
이 대답은 2020을 놀라게합니다.
Alex

25

두 가지 float값으로 코드를 호출하면 코드가 모든 범위에서 작동합니다.

float rand_FloatRange(float a, float b)
{
    return ((b - a) * ((float)rand() / RAND_MAX)) + a;
}

이것이 C99 또는 C ++ 11에서 잠재적 인 사용 사례 fmaf()(또는 fma()C ++ 의 부동 과부하)이며 더 정확한 정밀도를 유지할 수 있음을 언급 할 가치가 있습니다 . 에서처럼 fmaf((float)rand() / RAND_MAX, b - a, a).
Tim Čas

22

C가 아닌 C ++을 사용하는 경우 기술 보고서 ​​1 (TR1)과 C ++ 0x 초안에서 헤더 파일에 난수 생성기를위한 기능을 추가했다는 점을 기억하십시오. 부스트와 동일하다고 생각합니다. 랜덤 라이브러리이며 C 라이브러리 함수보다 훨씬 유연하고 "현대"랜드.

이 구문은 발전기 ( 메르 센 트위스터 mt19937 와 같은 )를 선택한 다음 분포 (일반, 베르누이, 이항 등) 를 선택할 수있는 기능을 제공합니다 .

구문은 다음과 같습니다 ( 이 사이트 에서 뻔뻔스럽게 빌림 ).

  #include <iostream>
  #include <random>

  ...

  std::tr1::mt19937 eng;  // a core engine class 
  std::tr1::normal_distribution<float> dist;     

  for (int i = 0; i < 10; ++i)        
      std::cout << dist(eng) << std::endl;

2
이것은 현재 C ++ 11에 있으며 dist는 min 및 max 값으로 초기화 할 수 있습니다.
Étienne

이니셜 라이저에 최소값과 최대 값을 넣고 값을 얻을 때 생성기를 제공하는 것이 이상하게 보입니다. 다른 방법이라면 좋을 것입니다.
yoyo

6

일부 시스템 (현재 VC 스프링이있는 Windows) RAND_MAX은 엄청나게 작습니다. 이자형. 15 비트 만 나누면 RAND_MAX23 개의 가능한 비트 대신 15 비트의 가수 만 생성됩니다. 이것은 문제가 될 수도 있고 아닐 수도 있지만이 경우 일부 값이 누락되었습니다.

아, 방금 그 문제에 대한 의견이 있다는 것을 알았습니다. 어쨌든, 당신을 위해 이것을 해결할 수있는 코드가 있습니다 :

float r = (float)((rand() << 15 + rand()) & ((1 << 24) - 1)) / (1 << 24);

테스트되지 않았지만 작동 할 수 있습니다 :-)


float r = (float) ((rand () << 9) | rand ()) / RAND_MAX는 어떻습니까? (또한 테스트되지 않음)
Trap

아아, 죄송합니다, RAND_MAX로 나누면 어디서나 당신을 데려 가지 않을 것입니다 ...이 트릭의 요점은 RAND_MAX보다 큰 무언가를 갖는 것입니다.
Joey

2
이론없이 난수를 작성하는 데주의하십시오. rand ()에 대한 연속 호출은 완전히 독립적이지 않을 수 있습니다. 힌트 : 선형 합동 발생기 인 경우 연속 호출에서 낮은 비트를보십시오. 0과 1 사이에서 번갈아 표시됩니다.
RBerteig

알아. 그러나 일부 응용 프로그램에서는 이것으로 충분할 수 있습니다. 그러나이 경우에는 두 개 이상의 통화를 사용해야합니다. 이 경우은 총알이 없으며 LCG라는 것에 의존 할 수도 없습니다. 다른 PRNG는 비트 수가 약합니다. 부스트 솔루션이 가장 좋습니다.
Joey

(nb : MSVC에서 rand가 반환 한 하위 비트는 RNG 상태의 가장 낮은 비트가 아닙니다. 100 개의 rand () 호출의 경우 1100100000111111101010010010011010101110110110111010011111100100000000010100011011000000100101100011을 얻습니다. Java는 48 비트 LCG를 사용하고 VC는 32 비트 만 사용합니다.
Joey


2

나는 지금까지 어떤 대답에도 만족하지 않았기 때문에 새로운 임의의 float 함수를 작성했습니다. float 데이터 형식에 대한 비트 가정을합니다. 여전히 최소 15 개의 임의 비트를 가진 rand () 함수가 필요합니다.

//Returns a random number in the range [0.0f, 1.0f).  Every
//bit of the mantissa is randomized.
float rnd(void){
  //Generate a random number in the range [0.5f, 1.0f).
  unsigned int ret = 0x3F000000 | (0x7FFFFF & ((rand() << 8) ^ rand()));
  unsigned short coinFlips;

  //If the coin is tails, return the number, otherwise
  //divide the random number by two by decrementing the
  //exponent and keep going. The exponent starts at 63.
  //Each loop represents 15 random bits, a.k.a. 'coin flips'.
  #define RND_INNER_LOOP() \
    if( coinFlips & 1 ) break; \
    coinFlips >>= 1; \
    ret -= 0x800000
  for(;;){
    coinFlips = rand();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    //At this point, the exponent is 60, 45, 30, 15, or 0.
    //If the exponent is 0, then the number equals 0.0f.
    if( ! (ret & 0x3F800000) ) return 0.0f;
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
  }
  return *((float *)(&ret));
}

7
흥미로운 접근 방식은, 나는 정말 무슨 일인지 이해하지 못하고, upvote에 싶지만 것
하센

2

내 의견으로는 위의 대답은 '임의의'플로트를 제공하지만 실제로는 임의의 플로트가 아닙니다 (즉, 플로트 표현의 일부를 놓친 것). 구현을 서두르 기 전에 먼저 float에 대한 ANSI / IEEE 표준 형식을 살펴 보겠습니다.

| 기호 (1 비트) | e (8 비트) | f (23 비트) |

이 단어가 나타내는 숫자는 (-1 * 부호) * 2 ^ e * 1.f입니다.

'e'숫자는 -127에서 126까지의 바이어스 된 (127의 바이어스를 갖는) 숫자입니다. 가장 간단한 (실제로는 가장 임의적 인) 함수는 임의의 int 데이터를 부동 소수점에 쓰는 것입니다. 그러므로

int tmp = rand();
float f = (float)*((float*)&tmp);

그렇게하면 float f = (float)rand();정수를 부동 소수점으로 변환합니다 (따라서 10은 10.0이됩니다).

이제 최대 값을 제한하려면 다음과 같이 할 수 있습니다 (작동하는지 확실하지 않음)

int tmp = rand();
float f = *((float*)&tmp);
tmp = (unsigned int)f       // note float to int conversion!
tmp %= max_number;
f -= tmp;

그러나 float의 구조를 보면 float의 최대 값은 (약) 2 ^ 127이며 int (2 ^ 32)의 최대 값보다 크므로 float로 표현할 수있는 숫자 이것이 내 최종 구현입니다.

/**
 * Function generates a random float using the upper_bound float to determine 
 * the upper bound for the exponent and for the fractional part.
 * @param min_exp sets the minimum number (closest to 0) to 1 * e^min_exp (min -127)
 * @param max_exp sets the maximum number to 2 * e^max_exp (max 126)
 * @param sign_flag if sign_flag = 0 the random number is always positive, if 
 *              sign_flag = 1 then the sign bit is random as well
 * @return a random float
 */
float randf(int min_exp, int max_exp, char sign_flag) {
    assert(min_exp <= max_exp);

    int min_exp_mod = min_exp + 126;

    int sign_mod = sign_flag + 1;
    int frac_mod = (1 << 23);

    int s = rand() % sign_mod;  // note x % 1 = 0
    int e = (rand() % max_exp) + min_exp_mod;
    int f = rand() % frac_mod;

    int tmp = (s << 31) | (e << 23) | f;

    float r = (float)*((float*)(&tmp));

    /** uncomment if you want to see the structure of the float. */
//    printf("%x, %x, %x, %x, %f\n", (s << 31), (e << 23), f, tmp, r);

    return r;
}

이 함수 randf(0, 8, 0)를 사용하면 0.0에서 255.0 사이의 난수가 반환됩니다.


1
당신은 실수가 있습니다. MAX_RAND가 일반적으로 (1 << 23)보다 낮으므로 rand () % frac_mod는 작동하지 않습니다.
DanielHsH

MAX_RAND의 정확한 크기를 모른다는 것을 인정해야합니다. 그것은 여전히 ​​작동하지 않을 것이며, 쓸모없는 진술 일 수도 있지만 여전히 작동 할 것입니다. 8 % 10 = 8이므로 문제가 없지만 MAX_RAND가 항상 작 으면 (1 << 23) 실제로 제거 할 수 있습니다.
user2546926

2
아뇨, 당신은 약간 틀 렸습니다. 랜드 맥스는 일반적으로 ~ 65,000입니다. 즉, 23 비트에서 15 개만 무작위로 만듭니다. 다른 것들은 아마도 0 일 것입니다. 실제로 임의의 숫자를 얻지 만 정밀도가 떨어집니다. 예를 들어 랜덤 제너레이터는 0.001과 0.002를 생성 할 수 있지만 0.0017은 생성 할 수 없습니다. 따라서 분포는 균일하지만 정밀도는 낮습니다 (플로트보다 정밀도가 256 배 낮음).
DanielHsH

이 답변에는 두 가지 실수가 있습니다. 지수 범위 고정 int e = (rand() % (max_exp - min_exp)) + min_exp_mod;및 가수 : int f = (int)(frac_mod * (float)rand() / RAND_MAX);위의 해당 줄을 교체하십시오. 가수 실수는 중요합니다. RAND_MAX작을수록 1 << 23하위 유효 비트 만 랜덤 화하고 항상 최상위 비트에 대해 0을 얻습니다!
BeyelerStudios

2

부동 소수점 형식이 IEEE 754 (인텔 및 ARM을 포함한 거의 모든 최신 CPU) 임을 알고 있으면 비트 단위 방법을 사용하여 임의의 정수에서 임의의 부동 소수점 수를 작성할 수 있습니다. 당신이 C ++ 11의에 액세스 할 수없는 경우에만 고려되어야한다 random또는 Boost.Random어떤 모두 훨씬 더 있습니다.

float rand_float()
{
    // returns a random value in the range [0.0-1.0)

    // start with a bit pattern equating to 1.0
    uint32_t pattern = 0x3f800000;

    // get 23 bits of random integer
    uint32_t random23 = 0x7fffff & (rand() << 8 ^ rand());

    // replace the mantissa, resulting in a number [1.0-2.0)
    pattern |= random23;

    // convert from int to float without undefined behavior
    assert(sizeof(float) == sizeof(uint32_t));
    char buffer[sizeof(float)];
    memcpy(buffer, &pattern, sizeof(float));
    float f;
    memcpy(&f, buffer, sizeof(float));

    return f - 1.0;
}

이것은 나눗셈을 사용하는 것보다 더 나은 분포를 줄 것입니다.


8
왜 이것이 "더 나은 분포"를 줄 것이라고 말했는지 모르겠습니다. 실제로 이것은 정확히와 동일한 분포를 합니다return (float)random23 / (1 << 23) . (예, 방금 기능을 테스트random32 하여 매개 변수로 사용하도록 함수를 수정 하고 0에서 최대 값까지의 모든 값에 대해 실행했습니다 (1 << 23)-1. 예, 실제로 분석법은으로 나누는 것과 정확히 동일한 결과를 제공합니다 1 << 23.)
Ilmari Karonen

1

C ++의 경우 dist변수로 지정된 범위 내에서 실수 부동 숫자를 생성 할 수 있습니다.

#include <random>  //If it doesnt work then use   #include <tr1/random>
#include <iostream>

using namespace std;

typedef std::tr1::ranlux64_base_01 Myeng; 
typedef std::tr1::normal_distribution<double> Mydist;

int main() { 
       Myeng eng; 
       eng.seed((unsigned int) time(NULL)); //initializing generator to January 1, 1970);
       Mydist dist(1,10); 

       dist.reset(); // discard any cached values 
       for (int i = 0; i < 10; i++)
       {
           std::cout << "a random value == " << (int)dist(eng) << std::endl; 
       }

       return (0);
}

1
이 답변에서 코드를 복사하여 붙여 넣었습니까? stackoverflow.com/a/1118739/1538531
Derek

사실 아니요. 그들이 얼마나 닮았는지를보고 약간 놀랐습니다! 그러나 엔진 생성기를 1970 년 1 월 1 일에 초기화했습니다.
Marco167

그럴 수 있지. 생성기를 시대로 초기화했지만 코드가 비슷하다는 것을 알았습니다!
Derek

TR1 예제를 제공하는 것이 조금 이상하다는 것을 알았습니다. 누가 C ++ 11과 달리 TR1을 사용해야하는 경우를 설명 할 수 있습니까?
Shafik Yaghmour 1:25에서

0

rand ()는 0에서 RAND_MAX 사이의 정수를 반환합니다. 0.0과 1.0 사이의 난수를 얻으려면 먼저 rand ()에 의한 int return을 float로 캐스트 한 다음 RAND_MAX로 나눕니다.


0
#include <cstdint>
#include <cstdlib>
#include <ctime>

using namespace std;

/* single precision float offers 24bit worth of linear distance from 1.0f to 0.0f */
float getval() {
    /* rand() has min 16bit, but we need a 24bit random number. */
    uint_least32_t r = (rand() & 0xffff) + ((rand() & 0x00ff) << 16);
    /* 5.9604645E-8 is (1f - 0.99999994f), 0.99999994f is the first value less than 1f. */
    return (double)r * 5.9604645E-8;
}

int main()
{
    srand(time(NULL));
...

두 가지 답변을 게시 할 수 없으므로 두 번째 해결책이 있습니다. log2 난수, 0.0f에 대한 거대한 바이어스이지만 실제로는 1.0f ~ 0.0f의 임의의 부동 소수점입니다.

#include <cstdint>
#include <cstdlib>
#include <ctime>

using namespace std;

float getval () {
    union UNION {
        uint32_t i;
        float f;
    } r;
    /* 3 because it's 0011, the first bit is the float's sign.
     * Clearing the second bit eliminates values > 1.0f.
     */
    r.i = (rand () & 0xffff) + ((rand () & 0x3fff) << 16);
    return r.f;
}

int main ()
{
    srand (time (NULL));
...
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.