Pergunta

Eu tenho uma matriz de valores duplas "Vals", eu preciso índice aleatoriamente em essa matriz e obter um valor. GenRandomNumber () retorna um número entre 0 e 1, mas nunca 0 ou 1. Eu estou usando Convert.ToInt32 para obter basicamente tudo para a esquerda da minha casa decimal, mas deve haver uma maneira mais eficiente de fazer isso?

Aqui está o meu código:

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

Graças

Atualização

Obrigado a todos aqueles que respondeu, mas sou obrigado a usar um MersenneTwister implementação de números aleatórios fornecido que tem método rand.NextDouble ()

Update 2

pensamento sobre esta um pouco mais, todos precisam I a fazer é gen um número aleatório entre 0 e array.length-1 e, em seguida, utilizar a que aleatoriamente índice para a matriz . comprimento valos é 2 ^ 20 = 1048576 assim gerando um int aleatória é suficiente. Eu observo o meu MersenneTwister tem um método:

public int Next(int maxValue)

Se eu chamá-lo como vals [rand.Next (vals.length-1)] que deve fazê-lo direito? Vejo também o MersenneTwister tem um construtor:

public MersenneTwister(int[] init)

Não sei o que isso é para, posso usar isso para preencher previamente os números aleatórios aceitáveis ??para o qual eu proporcionar um leque de 0 a vals.length?

FYI valos é um duplo conjunto de comprimento 1048576 particionamento da curva de distribuição normal. Estou basicamente utilizando este mecanismo para criar números distribuídos normalmente o mais rápido possível, o Monte Carlo utiliza a simulação de milhares de milhões de Normalmente distribuído números aleatórios cada dia para cada pouco ajuda.

Foi útil?

Solução

Tente usar um inteiro aleatório em vez disso:

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

Outras dicas

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

Onde RNG é

Random rng = new Random();

Eu acho que você tem a mais simples aplicação mais direta já identificados.

Mas se você está procurando ganhos de desempenho em seu algoritmo de indexação aleatório, você pode ser capaz de apenas ' rachadura ' o IEEE 754 codificado duplo em seu expoente e fração - e usar a fração módulo do o tamanho da matriz como um índice aleatório.

Esta técnica não é susceptível de ser criptograficamente segura - por isso, se que é uma consideração -. Não fazê-lo

Além disso, esta abordagem não tornar o código mais óbvio - eu iria ficar com a sua aplicação original, a menos maximizando o desempenho é a consideração. Como um aparte, a parte mais lenta desse processamento é mais provável a geração Mersenne Twister de números aleatórios.

Aqui está o código:

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

Você já pensou em usar a classe .NET aleatória?

Gostaria de usar Random.Next (Int32) , que retorna um valor menor do que o de entrada e> = zero. Passar o seu comprimento de matriz como entrada, e você tem um índice válido aleatório.

Como outras pessoas já observamos, System.Random tem um Next sobrecarga que vai fazer o que você já está pedindo.

Quanto ao seu comentário sobre Convert.ToInt32 e uma alternativa mais eficiente, você pode diretamente lançar um double a um 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];
}

Se você não tem restrição de usar a função aleatório, use a classe Random.

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

Else gostaria apenas de usar um elenco porque dá o comportamento correto -. Arredondamento para zero, em vez do número inteiro mais próximo como Convert.ToInt32() faz

public Double GetRandomValue(Double[] values)
{
    return values[(Int32)(GetNextRandomNumber() * values.Length)];
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top