Genera un flotante aleatorio entre 0 y 1

5 minutos de lectura

avatar de usuario
jini

Estoy tratando de generar un número aleatorio entre 0 y 1. Sigo leyendo sobre arc4random(), pero no hay información sobre cómo obtener un flotador de él. ¿Cómo hago esto?

  • No duplicados, esta parece ser la única pregunta explícitamente relacionada con los flotadores.

    – Pi

    29 de mayo de 2011 a las 8:56

avatar de usuario
vladimir

Valor aleatorio en [0, 1[ (including 0, excluding 1):

double val = ((double)arc4random() / UINT32_MAX);

A bit more details here.

Actual range is [0, 0.999999999767169356]como límite superior es (doble) 0xFFFFFFFF / 0x100000000.

  • Gracias. La respuesta más directa que he visto. Leeré su enlace y obtendré detalles adicionales sobre esto. Gracias de nuevo.

    – jini

    2 de marzo de 2011 a las 19:40

  • es raro que ARC4RANDOM_MAX debe definirse manualmente, pero 0x100000000 es 4294967296cual es ULONG_MAX + 1. ¿Dónde está documentado que arc4random()el máximo de es ULONG_MAX ¿de todos modos?

    – bobobobo

    15/09/2012 a las 16:53


  • @bobobobo, desde aquí: desarrollador.apple.com/library/mac/#documentation/Darwin/Reference/… La función arc4random() devuelve números pseudoaleatorios en el rango de 0 a (2**32)-1

    – Vladímir

    15 de septiembre de 2012 a las 17:18

  • En realidad, el valor debería ser 0xFFFFFFFF, (2**32)-1 == 0x100000000 – 0x1 == 0xFFFFFFFF == UINT32_MAX como lo indica actualmente Jörg Bühmann en el enlace.

    – Josejulio

    10 de diciembre de 2014 a las 16:51


  • ¡No se garantiza que los valores generados de esta manera se distribuyan uniformemente!

    – Kelin

    9 de junio de 2015 a las 8:05

avatar de usuario
jovan stankovic

// Seed (only once)
srand48(time(0));

double x = drand48();

// Swift version
// Seed (only once)
srand48(Int(Date().timeIntervalSince1970))

let x = drand48()

Las funciones drand48() y erand48() devuelven valores de punto flotante no negativos, de doble precisión, distribuidos uniformemente en el intervalo [0.0 , 1.0].

  • Esta debería ser la mejor respuesta.

    – John Riselvato

    22 ago 2013 a las 14:00

  • Tal vez necesites actualizar un poco la respuesta, yo leer en NSHipster que drand48 necesita ser inicializado una vez con una semilla. los documentación de manzana También sugiero que debe ser inicializado.

    – dulaccc

    02/09/2014 a las 13:39


  • La semilla es necesaria porque le da a este generador aleatorio un punto de partida para los cálculos. Sin ella, la secuencia aleatoria siempre sería la misma en todos los lanzamientos de aplicaciones.

    – Jovan Stankovic

    4 de febrero de 2017 a las 13:52

  • Esta es la mejor respuesta.

    – sabialandia

    26 de mayo de 2017 a las 10:42

  • Esta respuesta no es una respuesta de precisión óptima para un double. Consulte stackoverflow.com/a/34765674/1033581 sobre cómo lograr la mejor precisión.

    – Corazón

    21 de marzo de 2018 a las 1:31

avatar de usuario
Coeur

Para Swift 4.2+ ver: https://stackoverflow.com/a/50733095/1033581


A continuación, se incluyen recomendaciones para lograr una uniformidad correcta y una precisión óptima para ObjC y Swift 4.1.

Precisión de 32 bits (óptima para Float)

Valor aleatorio uniforme en [0, 1] (incluyendo 0.0 y 1.0), hasta 32 bits de precisión:

Obj-C:

float val = (float)arc4random() / UINT32_MAX;

Rápido:

let val = Float(arc4random()) / Float(UInt32.max)

Es óptimo para:

  • a Float (o Float32) que tiene una precisión significativa de 24 bits para su mantisa

Precisión de 48 bits (desaconsejada)

Es fácil lograr una precisión de 48 bits con drand48 (que utiliza arc4random_buf bajo el capó). Pero ten en cuenta que drand48 tiene defectos debido al requisito de semilla y también por ser subóptimo para aleatorizar los 52 bits de Double mantissa.

Valor aleatorio uniforme en [0, 1]precisión de 48 bits:

Rápido:

// seed (only needed once)
srand48(Int(Date.timeIntervalSinceReferenceDate))
// random Double value
let val = drand48()

Precisión de 64 bits (óptima para Double y Float80)

Valor aleatorio uniforme en [0, 1] (incluyendo 0.0 y 1.0), hasta 64 bits de precisión:

Rápidousando dos llamadas a arc4random:

let arc4random64 = UInt64(arc4random()) << 32 &+ UInt64(arc4random())
let val = Float80(arc4random64) / Float80(UInt64.max)

Rápidousando una llamada a arc4random_buf:

var arc4random64: UInt64 = 0
arc4random_buf(&arc4random64, MemoryLayout.size(ofValue: arc4random64))
let val = Float80(arc4random64) / Float80(UInt64.max)

Es óptimo para:

  • a Double (o Float64) que tiene una precisión significativa de 52 bits para su mantisa
  • a Float80 que tiene una precisión significativa de 64 bits para su mantisa

notas

Comparaciones con otros métodos

Las respuestas donde el rango excluye uno de los límites (0 o 1) probablemente sufran un sesgo de uniformidad y deben evitarse.

  • utilizando arc4random()la mejor precisión es 1/0xFFFFFFFF (UINT32_MAX)
  • utilizando arc4random_uniform()la mejor precisión es 1/0xFFFFFFFE (UINT32_MAX-1)
  • utilizando rand() (secretamente usando arc4random), la mejor precisión es 1 / 0x7FFFFFFF (RAND_MAX)
  • utilizando random() (secretamente usando arc4random), la mejor precisión es 1 / 0x7FFFFFFF (RAND_MAX)

Es matemáticamente imposible lograr una precisión superior a 32 bits con una sola llamada a arc4random, arc4random_uniform, rand o random. Por lo tanto, nuestras soluciones anteriores de 32 bits y 64 bits deberían ser las mejores que podamos lograr.

  • ‘Float80’ no está disponible en dispositivos iOS reales (solo funciona en simulador).

    – Corazón

    29 de noviembre de 2018 a las 9:14

Esta función también funciona para rangos flotantes negativos:

float randomFloat(float Min, float Max){
    return ((arc4random()%RAND_MAX)/(RAND_MAX*1.0))*(Max-Min)+Min;
}

avatar de usuario
Coeur

Rápido 4.2+

Swift 4.2 agrega soporte nativo para un valor aleatorio en un rango:

let x = Float.random(in: 0.0...1.0)
let y = Double.random(in: 0.0...1.0)
let z = Float80.random(in: 0.0...1.0)

Doc:

avatar de usuario
Frungi

(float)rand() / RAND_MAX

La publicación anterior que decía “rand ()” solo era incorrecta. Esta es la forma correcta de usar rand().

Esto creará un número entre 0 -> 1

Documentos BSD:

La función rand() calcula una secuencia de enteros pseudoaleatorios en el
rango de 0 a RAND_MAX (como se define en el archivo de encabezado “stdlib.h”).

Esta es la extensión para el número aleatorio flotante Rápido 3.1

// MARK: Float Extension

public extension Float {

    /// Returns a random floating point number between 0.0 and 1.0, inclusive.
    public static var random: Float {
        return Float(arc4random()) / Float(UInt32.max))
    }

    /// Random float between 0 and n-1.
    ///
    /// - Parameter n:  Interval max
    /// - Returns:      Returns a random float point number between 0 and n max
    public static func random(min: Float, max: Float) -> Float {
        return Float.random * (max - min) + min
    }
}

  • @Cœur Gracias, lo cambio.

    – Yann Steph

    27/09/2017 a las 20:11

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad