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?
ios
c
random
floating-point
arc4random
Jini
fonte
fonte
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.
fonte
ARC4RANDOM_MAX
tenha que ser definido manualmente, mas0x100000000
é 4294967296 , que éULONG_MAX + 1
. Onde está documentado quearc4random()
o máximo é deULONG_MAX
qualquer maneira?// Seed (only once) srand48(time(0)); double x = drand48(); // Swift version // Seed (only once) srand48(Int(Date().timeIntervalSince1970)) let x = drand48()
fonte
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.
Precisão de 32 bits (ideal para
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 :
É ideal para:
Float
(ouFloat32
) que tem uma precisão de significando de 24 bits para sua mantissaPrecisão de 48 bits (desencorajado)
É fácil atingir a precisão de 48 bits com
drand48
( que usaarc4random_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()
Precisão de 64 bits (ideal para
Double
eFloat80
)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
(ouFloat64
) 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 mantissaNotas
Comparações com outros métodos
As 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
ourandom
. Portanto, nossas soluções acima de 32 bits e 64 bits devem ser as melhores que podemos alcançar.fonte
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; }
fonte
Min+(Max-Min)*((float)arc4random())/ULONG_MAX
lugar. O(float)
elenco é apenas paranóia.Swift 4.2+
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:
random(in range: ClosedRange<Float>)
random(in range: Range<Float>)
random(in range: ClosedRange<Double>)
random(in range: Range<Double>)
random(in range: ClosedRange<Float80>)
random(in range: Range<Float80>)
fonte
(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
fonte
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 } }
fonte
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.
fonte
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.
fonte
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 emarc4random()*1.0 / UINT32_MAX
vez dearc4random_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();
fonte
float x = arc4random() % 11 * 0.1;
Isso produz uma flutuação aleatória entre 0 e 1. Mais informações aqui
fonte
por padrão, produz um número aleatório (float) entre 0 e 1.
fonte
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 comorand()
absolutamente existem no iOS, masarc4random()
é o preferido.