27 votos

Mejor manera de generar un flotador random en C#

¿Cuál es la mejor manera de generar un flotador random en C#?

Actualización: Quiero al azar números de coma flotante del flotador. MinValue a flotador. MaxValue. Estoy usando estos números en la unidad de prueba de algunos métodos matemáticos.

39voto

user7116 Puntos 39829

El mejor enfoque, no enloquecidos de valores, distribuidos con respecto a lo representable intervalos en el número de punto flotante de línea (eliminado "uniforme", como con respecto a un número continuo de la línea es decididamente no uniforme):

static float NextFloat(Random random)
{
    double mantissa = (random.NextDouble() * 2.0) - 1.0;
    double exponent = Math.Pow(2.0, random.Next(-126, 128));
    return (float)(mantissa * exponent);
}

Otro enfoque que se le dará algunos enloquecidos de valores (distribución uniforme de patrones de bits), que es potencialmente útil para la confusión:

static float NextFloat(Random random)
{
    var buffer = new byte[4];
    random.NextBytes(buffer);
    return BitConverter.ToSingle(buffer,0);
}

Menos enfoque útil:

static float NextFloat(Random random)
{
    // Not a uniform distribution w.r.t. the binary floating-point number line
    // which makes sense given that NextDouble is uniform from 0.0 to 1.0.
    // Uniform w.r.t. a continuous number line.
    //
    // The range produced by this method is 6.8e38.
    //
    // Therefore if NextDouble produces values in the range of 0.0 to 0.1
    // 10% of the time, we will only produce numbers less than 1e38 about
    // 10% of the time, which does not make sense.
    var result = (random.NextDouble()
                  * (Single.MaxValue - (double)Single.MinValue))
                  + Single.MinValue;
    return (float)result;
}

Número de punto flotante de la línea de: Arquitectura de Intel para Desarrolladores de Software Manual de Volumen 1: Arquitectura Básica. El eje Y es logarítmica (base 2) porque consecutivos binario de números de punto flotante no difieren de forma lineal.

Comparison of distributions, logarithmic Y-axis

14voto

Jon Skeet Puntos 692016

Cualquier razón para no usar Random.NextDouble y luego arrojado a float? Que le dará un flotador entre 0 y 1.

Si desea una forma diferente de "mejor" deberá especificar sus requisitos. Tenga en cuenta que Random no debe ser utilizado para asuntos delicados, tales como las finanzas o la seguridad - y que en general la reutilización de una instancia existente a lo largo de su aplicación, o uno por cada hilo (como Random no es thread-safe).

EDIT: Como se sugiere en los comentarios, para convertir esto en un rango de float.MinValue, float.MaxValue:

// Perform arithmetic in double type to avoid overflowing
double range = (double) float.MaxValue - (double) float.MinValue;
double sample = rng.NextDouble();
double scaled = (sample * range) + float.MinValue;
float f = (float) scaled;

EDIT: Ahora que usted ha mencionado que este es para la unidad de pruebas, no estoy seguro de que es un enfoque ideal. Probablemente, usted debe probar con valores concretos en su lugar, asegurándose de que usted prueba con las muestras en cada una de las categorías relevantes - infinitos, Nan, denormal números, números muy grandes, cero, etc.

0voto

Simon Mourier Puntos 49585

Otra solución es hacer esto:

static float NextFloat(Random random)
{
    float f;
    do
    {
        byte[] bytes = new byte[4];
        random.NextBytes(bytes);
        f = BitConverter.ToSingle(bytes, 0);
    }
    while (float.IsInfinity(f) || float.IsNaN(f));
    return f;
}

0voto

Anthony Pegram Puntos 58528

Tomé un enfoque ligeramente diferente de otros

static float NextFloat(Random random)
{
    double val = random.NextDouble(); // range 0.0 to 1.0
    val -= 0.5; // expected range now -0.5 to +0.5
    val *= 2; // expected range now -1.0 to +1.0
    return float.MaxValue * (float)val;
}

Los comentarios explican lo que estoy haciendo. Haz la siguiente doble, convertir ese número a un valor entre -1 y 1 y luego multiplicar eso con float.MaxValue .

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X