Estou tentando gerar um número aleatório entre 0 e 1. Continuo lendo sobre arc4random()
, mas não há nenhuma informação sobre como obter um float dele. Como eu faço isso?
Respostas:
Valor aleatório em [0, 1 [ (incluindo 0, excluindo 1):
double val = ((double)arc4random() / UINT32_MAX);
Um pouco mais de detalhes aqui .
O intervalo real é [0, 0,9999999999767169356] , pois o limite superior é (duplo) 0xFFFFFFFF / 0x100000000.
ARC4RANDOM_MAX
tenha que ser definido manualmente, mas 0x100000000
é 4294967296 , que é ULONG_MAX + 1
. Onde está documentado que arc4random()
o máximo é de ULONG_MAX
qualquer maneira?
// Seed (only once)
srand48(time(0));
double x = drand48();
// Swift version
// Seed (only once)
srand48(Int(Date().timeIntervalSince1970))
let x = drand48()
As funções drand48 () e erand48 () retornam valores não negativos, de dupla precisão, de ponto flutuante, uniformemente distribuídos no intervalo [0,0, 1,0].
drand48
precisa ser inicializado uma vez com uma semente. A documentação da Apple também sugere que ele deve ser inicializado.
double
. Consulte stackoverflow.com/a/34765674/1033581 para saber como obter a melhor precisão.
Para Swift 4.2+, consulte: https://stackoverflow.com/a/50733095/1033581
Abaixo estão as recomendações para uniformidade correta e precisão ideal para ObjC e Swift 4.1.
Float
)Valor aleatório uniforme em [0, 1] (incluindo 0,0 e 1,0), precisão de até 32 bits:
Obj-C :
float val = (float)arc4random() / UINT32_MAX;
Swift :
let val = Float(arc4random()) / Float(UInt32.max)
É ideal para:
Float
(ou Float32
) que tem uma precisão de significando de 24 bits para sua mantissaÉ fácil atingir a precisão de 48 bits com drand48
( que usa arc4random_buf
sob o capô ). Mas observe que drand48 tem falhas por causa do requisito de seed e também por ser subótimo para randomizar todos os 52 bits de Double mantissa.
Valor aleatório uniforme em [0, 1] , precisão de 48 bits:
Swift :
// seed (only needed once)
srand48(Int(Date.timeIntervalSinceReferenceDate))
// random Double value
let val = drand48()
Double
e Float80
)Valor aleatório uniforme em [0, 1] (incluindo 0,0 e 1,0), até 64 bits de precisão:
Swift , usando duas chamadas para arc4random:
let arc4random64 = UInt64(arc4random()) << 32 &+ UInt64(arc4random())
let val = Float80(arc4random64) / Float80(UInt64.max)
Swift , usando uma chamada para arc4random_buf:
var arc4random64: UInt64 = 0
arc4random_buf(&arc4random64, MemoryLayout.size(ofValue: arc4random64))
let val = Float80(arc4random64) / Float80(UInt64.max)
É ideal para:
Double
(ou Float64
) que tem uma precisão de significando de 52 bits para sua mantissaFloat80
que tem uma precisão de significando de 64 bits para sua mantissaAs respostas em que o intervalo exclui um dos limites (0 ou 1) provavelmente sofrem de um viés de uniformidade e devem ser evitadas.
arc4random()
, a melhor precisão é 1 / 0xFFFFFFFF (UINT32_MAX)arc4random_uniform()
, a melhor precisão é 1 / 0xFFFFFFFE (UINT32_MAX-1)rand()
( secretamente usando arc4random ), a melhor precisão é 1 / 0x7FFFFFFF (RAND_MAX)random()
( secretamente usando arc4random ), a melhor precisão é 1 / 0x7FFFFFFF (RAND_MAX)É matematicamente impossível atingir precisão melhor do que 32 bits com uma única chamada para arc4random
, arc4random_uniform
, rand
ou random
. Portanto, nossas soluções acima de 32 bits e 64 bits devem ser as melhores que podemos alcançar.
Esta função também funciona para intervalos de flutuação negativa:
float randomFloat(float Min, float Max){
return ((arc4random()%RAND_MAX)/(RAND_MAX*1.0))*(Max-Min)+Min;
}
Min+(Max-Min)*((float)arc4random())/ULONG_MAX
lugar. O (float)
elenco é apenas paranóia.
O Swift 4.2 adiciona suporte nativo para um valor aleatório em um intervalo:
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:
(float)rand() / RAND_MAX
O post anterior informando "rand ()" sozinho estava incorreto. Esta é a maneira correta de usar rand ().
Isso criará um número entre 0 -> 1
Documentos BSD:
A função rand () calcula uma sequência de inteiros pseudo-aleatórios no
intervalo de 0 a RAND_MAX (conforme definido pelo arquivo de cabeçalho "stdlib.h").
Esta é uma extensão para o número aleatório Float Swift 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
}
}
Swift 4.2
O Swift 4.2 incluiu uma API de número aleatório nativa e bastante completa na biblioteca padrão. ( Proposta de evolução rápida SE-0202 )
let intBetween0to9 = Int.random(in: 0...9)
let doubleBetween0to1 = Double.random(in: 0...1)
Todos os tipos de número têm a função aleatória estática (em :) que pega o intervalo e retorna o número aleatório no intervalo fornecido.
Use isso para evitar problemas com o limite superior de arc4random ()
u_int32_t upper_bound = 1000000;
float r = arc4random_uniform(upper_bound)*1.0/upper_bound;
Observe que é aplicável para MAC_10_7, IPHONE_4_3 e superior.
upper_bound-1
. Ainda assim, você ainda teria uma precisão arbitrariamente baixa causada por upper_bound, então você deveria aumentar upper_bound para UINT32_MAX. E você pode obter uma precisão ainda melhor usando em arc4random()*1.0 / UINT32_MAX
vez de arc4random_uniform(UINT32_MAX)*1.0 / (UINT32_MAX-1)
.
arc4random
tem um intervalo de até 0x100000000 (4294967296)
Esta é outra boa opção para gerar números aleatórios entre 0 e 1:
srand48(time(0)); // pseudo-random number initializer.
double r = drand48();
float x = arc4random() % 11 * 0.1;
Isso produz uma flutuação aleatória entre 0 e 1. Mais informações aqui
rand()
por padrão, produz um número aleatório (float) entre 0 e 1.
rand()
não parece existir no iOS e, se existisse , produziria um número inteiro como em todos os outros * NIX.
rand()
é parte de C, que por sua vez é parte de Objective-C (que é usado na programação iOS). Funções C como rand()
absolutamente existem no iOS, mas arc4random()
é o preferido.