Question

J'ai un tableau de valeurs doubles « vals », ai-je besoin d'indexer au hasard dans ce tableau et d'obtenir une valeur. GenRandomNumber () retourne un nombre compris entre 0 et 1 mais jamais 0 ou 1. J'utilise Convert.ToInt32 pour obtenir essentiellement tout à gauche de ma place décimale, mais il doit y avoir un moyen plus efficace de le faire?

Voici mon code:

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

Merci

Mise à jour

Merci à tous ceux qui ont répondu, mais je suis contraint d'utiliser une mise en œuvre de nombres aléatoires Mersenne Twister qui a fourni la méthode rand.NextDouble ()

Mise à jour 2

En pensant à ce un peu plus, tout ce que je dois faire est gen un nombre aléatoire entre 0 et array.length-1, puis l'utiliser pour indexer de façon aléatoire dans le tableau . vals longueur est 2 ^ 20 = 1.048.576 de sorte à générer un int aléatoire est suffisant. Je remarque que mon Mersenne Twister a une méthode:

public int Next(int maxValue)

Si je l'appelle comme vals [rand.Next (vals.length-1)] qui devrait le faire correctement? Je vois aussi le Mersenne Twister a un constructeur:

public MersenneTwister(int[] init)

Je ne sais pas ce que cela est pour, puis-je utiliser pour préremplir les nombres aléatoires acceptables pour lesquels je propose un tableau de 0 à vals.length?

FYI vals est une double rangée de longueur 1048576 divisant la courbe de distribution normale. J'utilise essentiellement ce mécanisme pour créer des nombres normalement distribués aussi rapidement que possible, utilise la simulation monte carlo milliards de nombres aléatoires Normalement distribués chaque jour pour chaque petit aide.

Était-ce utile?

La solution

Essayez d'utiliser à la place un entier aléatoire:

Random random = new Random();
int randomNumber = random.Next(0, vals.Length);
return vals[randomNumber];

Autres conseils

return vals[rng.Next(vals.Length)];

Où RNG est

Random rng = new Random();

Je pense que vous avez la mise en œuvre la plus directe la plus simple déjà identifié.

Mais si vous êtes à la recherche de gains de performance dans votre algorithme d'indexation aléatoire, vous pourrez peut-être juste « fissure » IEEE 754 codé à double dans son exposant et fraction - et utiliser la fraction modulo la la taille de la matrice comme un index aléatoire.

Cette technique ne risque pas d'être sûr cryptographiquement - donc si c'est une considération -. Ne le faites pas

En outre, cette approche ne pas rendre le code plus évident - je collerait avec votre mise en œuvre initiale, à moins maximiser la performance est la contrepartie. En aparté, la partie la plus lente de ce traitement est très probablement la génération Mersenne Twister de nombres aléatoires.

Voici le code:

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

Avez-vous pensé à utiliser la classe aléatoire .NET?

J'utiliser Random.Next (Int32) , qui renvoie une valeur inférieure à l'entrée et> = zéro. Passez votre longueur du tableau que l'entrée, et vous avez un index valide aléatoire.

Comme d'autres personnes ont déjà noté, System.Random a une surcharge suivante qui fera ce que vous vous demandez déjà.

Quant à vos commentaires sur Convert.ToInt32 et une alternative plus efficace, vous pouvez directement jeter un double à un int:

double d = 1.5;
int i = (int)d;
private static readonly Random _random = new Random();

public double GetRandomVal()
{
    int z = _random.Next(vals.Length);
    return vals[z];
}

Si vous n'êtes pas contrainte d'utiliser votre fonction aléatoire, utilisez la classe Random.

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

Sinon je voudrais simplement utiliser un casting car il donne le bon comportement -. Arrondi vers zéro au lieu de l'entier le plus proche que Convert.ToInt32() fait

public Double GetRandomValue(Double[] values)
{
    return values[(Int32)(GetNextRandomNumber() * values.Length)];
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top