3

double値「vals」の配列があります。この配列にランダムにインデックスを付けて値を取得する必要があります。GenRandomNumber()は0から1までの数値を返しますが、0または1は返しません。Convert.ToInt32を使用して基本的にすべてを小数点以下の桁数の左側に配置していますが、これを行うより効率的な方法が必要ですか?

これが私のコードです:

public double GetRandomVal()
{
   int z = Convert.ToInt32(GenRandomNumber() * (vals.Length));
   return vals[z];
}

ありがとう

アップデート

返信してくれたすべての人に感謝しますが、メソッドrand.NextDouble()を持つ提供されたMersenneTwister乱数実装を使用するように制約されています

アップデート2

これについてもう少し考えてみると、私がする必要があるのは、0からarray.length-1までの乱数を生成し、それを使用して配列にランダムにインデックスを付けることです。valsの長さは2^20 = 1048576であるため、ランダムなintを生成するだけで十分です。MersenneTwisterには次の方法があることに気付きました。

public int Next(int maxValue)

vals [rand.Next(vals.length-1)]のように呼んだら、正しく機能するはずです。MersenneTwisterにはコンストラクターがあることもわかります。

public MersenneTwister(int[] init)

これが何のためにあるのかわからないので、これを使用して、0からvals.lengthの配列を提供する許容可能な乱数を事前入力できますか?

FYI valsは、正規分布曲線を分割する長さ1048576の二重配列です。私は基本的にこのメカニズムを使用して、正規分布の数値をできるだけ速く作成しています。モンテカルロシミュレーションでは、毎日数十億の正規分布の乱数を使用するため、少しでも役立ちます。

4

8 に答える 8

12

代わりにランダムな整数を使用してみてください。

Random random = new Random();
int randomNumber = random.Next(0, vals.Length);
return vals[randomNumber];
于 2009-07-20T17:41:32.193 に答える
3
return vals [rng.Next(vals.Length)];

rngはどこにありますか

Random rng = new Random();

于 2009-07-20T17:42:05.560 に答える
2

最も単純で直接的な実装がすでに特定されていると思います。

しかし、ランダム インデックス アルゴリズムでパフォーマンスの向上を探している場合は、IEEE 754 でエンコードされた double を指数と分数に分解し、配列サイズを法とする分数をランダム インデックスとして使用することができます

この手法は、暗号学的に安全である可能性が低いため、それが考慮される場合は、使用しないでください。

また、このアプローチではコードがより明確になるわけではありません。パフォーマンスを最大化することが考慮されない限り、元の実装に固執します。余談ですが、この処理の最も遅い部分は、おそらく乱数の Mersenne Twister 生成です。

コードは次のとおりです。

[StructLayout(LayoutKind.Explicit)] // used create a union of Long and Double
public struct IEEE754
{
    private const ulong SIGN_BITS     = 0x8000000000000000;
    private const ulong EXPONENT_BITS = 0x7FF0000000000000;
    private const ulong FRACTION_BITS = 0x000FFFFFFFFFFFFF;

    private const int SIGN_OFFSET     = 63;
    private const int EXPONENT_OFFSET = 52;

    // [FieldOffset] attribute is .NET's way of defining how to explicitly
    // layout the fields of a structure - we're using it to overlay the
    // double and long into a single bit-space ... effectively a C# 'union'
    [FieldOffset( 0 )] private double DoubleValue;
    [FieldOffset( 0 )] private ulong LongValue;

    public IEEE754(double val)
    {
        DoubleValue = val;
    }
    // properties that retrieve the various pieces of an IEEE754 double
    public long Fraction { get { return (long)(LongValue & FRACTION_BITS); } }
    public long Exponent { get { return (long)((LongValue & EXPONENT_BITS) >> EXPONENT_OFFSET); } }
    public long Sign     { get { return (long)((LongValue & SIGN_BITS) >> SIGN_OFFSET); } }

    public void Set( double val ) { DoubleValue = val; }
}

public static void TestFunction()
{
    var array = Enumerable.Range( 1, 10000 ).ToArray();   // test array...

    // however you access your random generator would go here...
    var rand = new YourRandomNumberGenerator();

    // crack the double using the special union structure we created...
    var dul = new IEEE754( rand.GenRandomNumber() );

    // use the factional value modulo the array length as a random index...
    var randomValue = array[dul.Fraction % array.Length];
}
于 2009-07-20T18:38:31.390 に答える
0
private static readonly Random _random = new Random();

public double GetRandomVal()
{
    int z = _random.Next(vals.Length);
    return vals[z];
}
于 2009-07-20T17:42:34.280 に答える
0

.NET Randomクラスの使用を検討しましたか?

于 2009-07-20T17:42:46.357 に答える
0

Random.Next(Int32)を使用します。これは、入力よりも小さい値を返し、ゼロ以上です。配列の長さを入力として渡すと、ランダムな有効なインデックスが得られます。

于 2009-07-20T17:43:21.487 に答える
0

他の人がすでに指摘しているように、System.Random には、すでに求めていることを実行する Next オーバーロードがあります。

より効率的な代替案についてのコメントについてはConvert.ToInt32、 adoubleを an に直接キャストできintます。

double d = 1.5;
int i = (int)d;
于 2009-07-20T17:44:23.933 に答える
-1

ランダム関数を使用する制約がない場合は、Randomクラスを使用してください。

public Double GetRandomValue(Double[] values)
{
    return values[new Random().Next(values.Length)];
}

それ以外の場合は、正しい動作が得られるため、キャストを使用します-最も近い整数の代わりにゼロに向かって丸めますConvert.ToInt32()

public Double GetRandomValue(Double[] values)
{
    return values[(Int32)(GetNextRandomNumber() * values.Length)];
}
于 2009-07-20T17:43:51.703 に答える