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_MAXManuel olarak tanımlanması gereken garip , ancak 0x1000000004294967296 , yani ULONG_MAX + 1. Nerede o belgelenmiştir arc4random()'ın max ULONG_MAXnası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.
drand48ihtiyacı 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_bufbaş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()
Doubleve 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)Float80kendi 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, randveya 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_MAXyerine. (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_MAXbunun 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.