web-dev-qa-db-ja.com

rand()0〜1

したがって、次のコードは0 <r <1になります

r = ((double) Rand() / (Rand_MAX))

r = ((double) Rand() / (Rand_MAX + 1))が-1 <r <0になるのはなぜですか?

Rand_MAXに1を追加すると1 <r <2になりませんか?

編集:私は警告を受けていました:式の整数オーバーフロー

その行で、それが問題になるかもしれません。 cout << r << endlを実行しましたが、-1〜0の値が確実に表示されます

66
CyberShot

これは完全に実装固有ですが、作業しているC++環境では、Rand_MAXINT_MAXと等しいようです。

このため、Rand_MAX + 1は未定義の(オーバーフロー)動作を示し、INT_MINになります。最初のステートメントは分割(0からINT_MAXの間のランダム#)と(INT_MAX)で値0 <= r < 1を生成していましたが、現在は分割(0からINT_MAXの間のランダム#)/(INT_MIN)で値-1 < r <= 0を生成しています

乱数1 <= r < 2を生成するには、次のようにします

r = ((double) Rand() / (Rand_MAX)) + 1
76
Sam DeHaan

Rand() / double(Rand_MAX)は、0(包括的)から1(包括的)の間の浮動小数点乱数を生成しますが、以下には適していません理由(Rand_MAXは通常32767であるため):

  1. 生成できる異なる乱数の数は、32768です。さらに異なる乱数が必要な場合は、別の方法が必要です(コード例を以下に示します)。
  2. 生成された数値は粗すぎます。1/ 32768、2/32768、3/32768を取得できますが、その間には何もありません。
  3. 乱数生成エンジンの制限された状態:Rand_MAX乱数を生成した後、実装は通常、同じ乱数シーケンスを繰り返し始めます。

Rand()の上記の制限により、0(包括的)から1(exclusive)の間の乱数生成のより良い選択は次のようになります。スニペット( http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution の例と同様):

#include <iostream>
#include <random>
#include <chrono>

int main()
{
    std::mt19937_64 rng;
    // initialize the random number generator with time-dependent seed
    uint64_t timeSeed = std::chrono::high_resolution_clock::now().time_since_Epoch().count();
    std::seed_seq ss{uint32_t(timeSeed & 0xffffffff), uint32_t(timeSeed>>32)};
    rng.seed(ss);
    // initialize a uniform distribution between 0 and 1
    std::uniform_real_distribution<double> unif(0, 1);
    // ready to generate random numbers
    const int nSimulations = 10;
    for (int i = 0; i < nSimulations; i++)
    {
        double currentRandomNumber = unif(rng);
        std::cout << currentRandomNumber << std::endl;
    }
    return 0;
}

unif(0, 1)unif(1, 2)に置き換えることにより、1(包括的)から2(排他的)の間の乱数を生成するように簡単に変更できます。

23
Serge Rogatch

いいえ、Rand_MAXは通常MAX_INTに拡張されるためです。そのため、1つ(明らかに)を追加すると、MIN_INTに配置されます(ただし、私が言ったように未定義の動作であるはずです)。したがって、符号が反転します。

必要なものを取得するには、計算の外側に+1を移動する必要があります。

r = ((double) Rand() / (Rand_MAX)) + 1;
17
Tudor

そうではありません。 0 <= r < 1になりますが、オリジナルは0 <= r <= 1です。

これは、Rand_MAX + 1がオーバーフローした場合に未定義の動作につながる可能性があることに注意してください。

3
Luchian Grigore

私の推測では、Rand_MAXINT_MAXと等しいので、負の値にオーバーフローしています。

これを行うだけです:

r = ((double) Rand() / (Rand_MAX)) + 1;

さらに良いことに、C++ 11の乱数ジェネレーターを使用します。

3
Pubby

これは正しい方法です:

double randd() {
  return (double)Rand() / ((double)Rand_MAX + 1);
}

または

double randd() {
  return (double)Rand() / (Rand_MAX + 1.0);
}
1
KIM Taegyoon

私の場合(私はVS 2017を使用しています)、次の簡単なコードでうまく動作します:

#include "pch.h"
#include <iostream>
#include <stdlib.h>
#include <time.h>

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

    for (int i = 1000; i > 0; i--) //try it thousand times
    {
        int randnum = (double)Rand() / ((double)Rand_MAX + 1);
        std::cout << " rnum: " << Rand()%2 ;
    }
} 
0
SeveneduS