0 ile 1 arasında rastgele bir sayı oluşturmaya çalışıyorum. Okumaya devam ediyorum arc4random()
, ancak ondan bir kayan nokta elde etme konusunda herhangi bir bilgi yok. Bunu nasıl yaparım?
Yanıtlar:
[0, 1 [ (0 dahil , 1 hariç) içinde rastgele değer :
double val = ((double)arc4random() / UINT32_MAX);
Daha ayrıntı bit burada .
Üst sınır (çift) 0xFFFFFFFF / 0x100000000 olduğundan gerçek aralık [0, 0.999999999767169356] şeklindedir.
ARC4RANDOM_MAX
Manuel olarak tanımlanması gereken garip , ancak 0x100000000
4294967296 , yani ULONG_MAX + 1
. Nerede o belgelenmiştir arc4random()
'ın max ULONG_MAX
nasıl olsa?
// Seed (only once)
srand48(time(0));
double x = drand48();
// Swift version
// Seed (only once)
srand48(Int(Date().timeIntervalSince1970))
let x = drand48()
Drand48 () ve erand48 () işlevleri, [0.0, 1.0] aralığında eşit olarak dağıtılmış, negatif olmayan, çift duyarlıklı, kayan noktalı değerleri döndürür.
drand48
ihtiyacı bir tohum ile bir kez başlatılıyor. Elma belgelerine de başlatıldı gerektiğini düşündürmektedir.
double
. En iyi hassasiyetin nasıl elde edileceğini öğrenmek için stackoverflow.com/a/34765674/1033581 sayfasına bakın .
Swift 4.2+ için bkz .: https://stackoverflow.com/a/50733095/1033581
Aşağıda, ObjC ve Swift 4.1 için doğru tekdüzelik ve optimum hassasiyet için öneriler bulunmaktadır.
Float
)[0, 1] 'de (0.0 ve 1.0 dahil) tek tip rasgele değer, 32 bit hassasiyete kadar:
Obj-C :
float val = (float)arc4random() / UINT32_MAX;
Swift :
let val = Float(arc4random()) / Float(UInt32.max)
Şunlar için idealdir:
Float
(veya Float32
)Bu 48 bit hassasiyet elde etmek kolaydır drand48
( ki kullanımları arc4random_buf
başlık altında ). Ancak drand48'in tohum gereksinimi nedeniyle kusurları olduğunu ve ayrıca 52 bitlik Double mantis'in tümünü rastgele hale getirmek için yetersiz kaldığını unutmayın .
[0, 1] , 48 bit hassasiyette tek tip rasgele değer :
Swift :
// seed (only needed once)
srand48(Int(Date.timeIntervalSinceReferenceDate))
// random Double value
let val = drand48()
Double
ve için en uygun Float80
)[0, 1] 'de (0.0 ve 1.0 dahil) tek tip rasgele değer, 64 bit hassasiyete kadar:
Swift , arc4random'a iki çağrı kullanarak:
let arc4random64 = UInt64(arc4random()) << 32 &+ UInt64(arc4random())
let val = Float80(arc4random64) / Float80(UInt64.max)
Swift , arc4random_buf için bir çağrı kullanarak:
var arc4random64: UInt64 = 0
arc4random_buf(&arc4random64, MemoryLayout.size(ofValue: arc4random64))
let val = Float80(arc4random64) / Float80(UInt64.max)
Şunlar için idealdir:
Double
(veya Float64
)Float80
kendi mantis için 64 bitlik bir significand hassas olanAralığın sınırlardan birini (0 veya 1) hariç tuttuğu cevaplar muhtemelen tekdüzelik önyargısından muzdariptir ve bundan kaçınılmalıdır.
arc4random()
, en hassas 1 / 0xFFFFFFFF (UINT32_MAX) olduğuarc4random_uniform()
, en hassas, 1 / 0xFFFFFFFE (UINT32_MAX-1)rand()
( gizlice arc4random kullanarak ), en iyi hassasiyet 1 / 0x7FFFFFFF (RAND_MAX)random()
( gizlice arc4random kullanarak ), en iyi hassasiyet 1 / 0x7FFFFFFF (RAND_MAX)Bu tek bir çağrı ile daha iyi 32 bit hassasiyet elde etmek matematiksel olarak imkansız arc4random
, arc4random_uniform
, rand
veya random
. Dolayısıyla, 32 bit ve 64 bitlik çözümlerimiz elde edebileceğimizin en iyisi olmalıdır.
Bu işlev, negatif kayan aralıklar için de çalışır:
float randomFloat(float Min, float Max){
return ((arc4random()%RAND_MAX)/(RAND_MAX*1.0))*(Max-Min)+Min;
}
Min+(Max-Min)*((float)arc4random())/ULONG_MAX
yerine. (float)
Dökme sadece paranoya.
Swift 4.2, bir Aralıktaki rastgele bir değer için yerel destek ekler:
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
Tek başına "rand ()" yazan bir önceki gönderi yanlıştı. Rand () kullanmanın doğru yolu budur.
Bu 0 -> 1 arasında bir sayı oluşturacaktır
BSD belgeleri:
Rand () işlevi
, 0 ila RAND_MAX aralığında ("stdlib.h" başlık dosyasıyla tanımlandığı gibi) sözde rasgele tamsayılar dizisini hesaplar .
Bu, Float rasgele sayı Swift 3.1'in bir uzantısıdır
// 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
Swift 4.2, standart kitaplığa yerel ve oldukça tam özellikli bir rastgele sayı API'si içeriyor. ( Swift Evolution önerisi SE-0202 )
let intBetween0to9 = Int.random(in: 0...9)
let doubleBetween0to1 = Double.random(in: 0...1)
Tüm sayı türleri , aralığı alan ve verilen aralıktaki rastgele sayıyı döndüren statik rasgele (in :) işlevine sahiptir.
Arc4random () öğesinin üst sınırıyla ilgili sorunları önlemek için bunu kullanın
u_int32_t upper_bound = 1000000;
float r = arc4random_uniform(upper_bound)*1.0/upper_bound;
MAC_10_7, IPHONE_4_3 ve üstü için geçerli olduğunu unutmayın.
upper_bound-1
. Yine de, üst sınırın neden olduğu keyfi olarak düşük bir hassasiyete sahip olursunuz, bu nedenle üst sınırı UINT32_MAX'a yükseltmelisiniz. Ve arc4random()*1.0 / UINT32_MAX
bunun yerine kullanarak daha da iyi hassasiyet elde edebilirsiniz arc4random_uniform(UINT32_MAX)*1.0 / (UINT32_MAX-1)
.
arc4random
0x100000000 (4294967296) kadar bir aralığı vardır
Bu, 0 ile 1 arasında rastgele sayılar oluşturmak için başka bir iyi seçenektir:
srand48(time(0)); // pseudo-random number initializer.
double r = drand48();
float x = arc4random() % 11 * 0.1;
Bu, onbeş 0 ve 1 arasında rastgele bir kayan nokta üretir. Daha fazla bilgi burada
rand()
varsayılan olarak 0 ile 1 arasında rastgele bir sayı (kayan) üretir.
rand()
iOS'ta yok gibi görünüyor ve eğer varsa, diğer * NIX'lerde olduğu gibi bir tamsayı üretecekti.
rand()
, sırasıyla Objective-C'nin (iOS programlamasında kullanılan) bir parçası olan C'nin bir parçasıdır. C rand()
, iOS'ta kesinlikle var gibi çalışır , ancak arc4random()
tercih edilir.