Arc4random_uniform () için range arasında nasıl rastgele sayı yapılır?


129

bu yüzden bu kod parçasındaki amacım rastgele iki zar atmak ve hepimizin bildiği gibi sizin normal kalıbınızın sadece 6 yüzü var, bu yüzden arc4random_uniform'a (UInt32) erişim için Foundation'ı ithal ettim. Rastgele 0 almaktan kaçınmak için (1..7) aralığını kullanmaya çalıştım, ancak bu çok hoşuma gitmeyen bir hata döndürdü. Bunu yapmaya çalıştım:

dice1 = arc4random_uniform(UInt32(1..7))

ancak geri döndü

Sağlanan bağımsız değişkenleri kabul eden 'init' için bir aşırı yükleme bulunamadı

Umarım bu, bana yardımcı olacak harika borçlar için yeterli bilgidir :)

Lütfen bunu bir oyun alanında hızlı pratik yapmak için yapıyorum. Bunu nasıl yapacağımı öğrenmem zorunlu değil; gerçek uygulamaları geliştirmeye başlamadan önce sadece ben kurcalayan benim: D

//imports random number function
import Foundation
//creates data storage for dice roll
var dice1: UInt32 = 0
var dice2: UInt32 = 0
//counter variable
var i = 0
//how many times snake eyes happens
var snakeeyes = 0
 //how many times a double is rolled
var `double` = 0
//rolls dice 100 times
while i < 100{
    //from here
    //sets dice roll

Bu, 'Aralık $ T3' hatası, UInt32'ye dönüştürülemiyor

   dice1 = arc4random_uniform(1..7)
   dice2 = arc4random_uniform(1..7)
    //checks for snake eyes
    if dice1 == 1 && dice2 == 1 {
        snakeeyes = snakeeyes + 1

    }
    //checks for doubles
    if dice1 == dice2{
        `double` = `double` + 1
    }
    //increases counter
        i = i + 1
    //to here
}
println("You got Snake Eyes \(snakeeyes) times.")
println("You got Doubles, \(`double`) times.")

4
dice1 = arc4random_uniform(6) + 11 - 6 aralığına ulaşmak için yapmanız gerektiğine inanıyorum. İOS hedefi C'yi yapmıyorum ve yine de hızlı dil hakkında herhangi bir bilgim yok. Rastgele yöntem size 0 - 5 döndürmeli ve + 1 1 - 6 olacaktır.
Gökyüzü

1
Aralık bir nesne verisidir, tam sayı verisi değildir, bu nedenle hata yalnızca argüman girdiğinde (UInt32) -u_int32_t arc4random_uniform(u_int32_t upper_bound);
Sky

Aha! teşekkürler gökyüzü! 0'dan daha az gidip gitmediğini test etmek için bir iddia yaptı ve bunun tam olarak ihtiyacım olan şey olduğunu doğrulayabilir ve bunu bir cevap olarak koyabilirim, böylece kontrol edebilirim!
arcreigh

olasılık = Int (arc4random_uniform (UInt32 (toplam))) - spesifik olmayan birden fazla döküm şikayetiniz varsa (çünkü
öndeki

Yanıtlar:


260

Yapman gerektiğine inanıyorum

dice1 = arc4random_uniform(6) + 1;

1 - 6 aralığını elde etmek için. iOS hedefi C'yi yapmıyorum ve yine de hızlı dil hakkında herhangi bir bilgim yok. Rastgele yöntem, 0 ile 5 arasında bir değer döndürmelidir ve + 1, onu 1 ile 6 arasında bir değer yapar.

10 - 30 arasında bir aralığa ihtiyacınız varsa,

int random = arc4random_uniform(21) + 10;

2
@JoeSmith tam olarak bu konuda haklısınız, üst sınır kapsayıcı olmadığından 10 - 30 arasında bir aralık döndürmek için arc4random_uniform (21) +10 olmalıdır. "Arc4random_uniform (20) +10" bölümü topluluk düzenlemesi ve oylamasına dayanmaktadır.
Sky

Evet, az önce test ettim ve rastgele bir renk elde etmek için (yani, 0 - 255 arasında rastgele bir değer isteyen), kullandım: "arc4random_uniform (256) + 0"
Chris Allinson

91

Int tipi bir uzantı yaptım. oyun alanında test etti, umarım bu yararlıdır. Negatif aralıkları da kabul eder:

extension Int
{
    static func random(range: Range<Int> ) -> Int
    {
        var offset = 0

        if range.startIndex < 0   // allow negative ranges
        {
            offset = abs(range.startIndex)
        }

        let mini = UInt32(range.startIndex + offset)
        let maxi = UInt32(range.endIndex   + offset)

        return Int(mini + arc4random_uniform(maxi - mini)) - offset
    }
}

gibi kullan

var aRandomInt = Int.random(-500...100)  // returns a random number within the given range.

veya aşağıdaki gibi bir Aralık uzantısı olarak tanımlayın:

extension Range
{
    var randomInt: Int
    {
        get
        {
            var offset = 0

            if (startIndex as Int) < 0   // allow negative ranges
            {
                offset = abs(startIndex as Int)
            }

            let mini = UInt32(startIndex as Int + offset)
            let maxi = UInt32(endIndex   as Int + offset)

            return Int(mini + arc4random_uniform(maxi - mini)) - offset
        }
    }
}

// usage example: get an Int within the given Range:
let nr = (-1000 ... 1100).randomInt

6
Uzantınız güzel: 3 Swift'in gerçek bir kullanımı!
Kalzem

Range uzantısını beğendim.
David James

İyi cevap. Tek uyarım, randomInt: Int veya Range'in doğal bir uzantısı olmadığını söylemek olacaktır. Bunu bir yardımcı program dosyasına bağımsız bir işlev olarak eklerdim.
Vince O'Sullivan

Swift 3 için güncellenmesi gerekiyor, range.startIndex'i bunun yerine range.lowerBound ile değiştirin ve endIndex artık UpperBound
Joseph Astrahan

62

Oldukça iyi yanıtlar, ancak pozitif tam sayılar için kişisel favorim olan Swift rastgele sayı oluşturma işlevini paylaşmak istedim:

Swift 2

func randomNumber(range: Range<Int> = 1...6) -> Int {
    let min = range.startIndex
    let max = range.endIndex
    return Int(arc4random_uniform(UInt32(max - min))) + min
}

Hızlı 3

İşte Swift 3 için hızlı bir güncelleme ve bir bonus olarak, artık SignedInteger protokolüne uyan herhangi bir değer türü için çalışıyor - Int16, Int32 vb. Belirtmesi gereken çekirdek veri uygulamaları için çok daha uygun. gerçekten sadece o yerine tüm işlevini kopya yanı tamsayılar üzerinde çalışmaya ihtiyaç SignedIntegerile UnsignedIntegerve toIntMax()ile toUIntMax().

func randomNumber<T : SignedInteger>(inRange range: ClosedRange<T> = 1...6) -> T {
    let length = (range.upperBound - range.lowerBound + 1).toIntMax()
    let value = arc4random().toIntMax() % length + range.lowerBound.toIntMax()
    return T(value)
}

Swift 4

Swift 4'te toIntMax () 'ın kaldırılması sayesinde, artık ortak bir tam sayı türüne dönüştürmek için farklı bir yol kullanmak zorundayız. Bu örnekte, amaçlarım için yeterince büyük olan Int64 kullanıyorum, ancak işaretsiz tamsayılar kullanıyorsanız veya bir Int128 veya Int256 özel türüne sahipseniz, bunları kullanmalısınız.

public func randomNumber<T : SignedInteger>(inRange range: ClosedRange<T> = 1...6) -> T {
    let length = Int64(range.upperBound - range.lowerBound + 1)
    let value = Int64(arc4random()) % length + Int64(range.lowerBound)
    return T(value)
}

Bir tane daha, toplam rastgele filme için, burada herhangi bir Collectiontür nesnesinden rastgele bir öğe döndüren bir uzantı var . Bunun, indeksini oluşturmak için yukarıdaki işlevi kullandığını ve bu nedenle ikisine de ihtiyacınız olacağını unutmayın.

extension Collection {
    func randomItem() -> Self.Iterator.Element {
        let count = distance(from: startIndex, to: endIndex)
        let roll = randomNumber(inRange: 0...count-1)
        return self[index(startIndex, offsetBy: roll)]
    }
}

kullanım

randomNumber()

1 ile 6 arasında rastgele bir sayı döndürür.

randomNumber(50...100)

50 ile 100 arasında bir sayı döndürür. Doğal olarak 50 ve 100 değerlerini istediğiniz gibi değiştirebilirsiniz.

Swift 4.2

Ne yazık ki, en iyi StackOverflow cevabım sonunda geçersiz hale geldi. Artık Int.random(in: 1 ... 6)belirli bir aralıkta rastgele bir sayı oluşturmak için kullanabilirsiniz . Diğer tam sayı ve kayan noktalı sayı biçimleri için de çalışır. Koleksiyon türleri de artık sağlar shuffle()ve randomElement()işlev görür. Bu nedenle, belirli bir rasgele dağıtıcı türü kullanmak istemediğiniz sürece artık süslü rasgeleleştirme işlevlerine gerek yoktur.


1
Buna baktım ve yanlış olması gerektiğini düşündüm çünkü (maks - min) = 5, 0 ila 4 aralığında rastgele bir tam sayı veriyor (artı 1, 1 ila 5 yapıyor). Ancak kodu bir Xcode oyun alanına yerleştirerek işe yaradığı açıktı. EndIndex, "Koleksiyonun ilk 'sondan sonraki' konumunu" döndürdüğü için max'ın aslında 7'ye eşit olmasının nedeni. (Apple'ın belgelerinde belirtildiği gibi). Bu yüzden iyi bir cevap ve benim için faydalı bir öğrenme alıştırması.
Vince O'Sullivan

Bu, negatif tamsayılarla da çalışır. randomNumber(-3 ... -1)öncesinde ve sonrasında boşluklarınız olduğu sürece çalışır .... random(-3 ..< -1Son sayıyı hariç tutmak için de kullanabilirsiniz .
Carter Medlin

ClosedIntervalBunun Rangetamsayı olmayanlarla çalışmasını istiyorsanız bunun yerine kullanın .
Carter Medlin

Yapmazdım. Aralık türleri Swift 3'te kullanımdan kaldırıldı. Kodun işlevselliğini genişletmek için Generics'i kullanmanın muhtemelen bir yolu var, ancak araştırmak için zamanım, eğilimim veya nedenim olmadı.
Ash

1
İşte kodun jenerik tamsayı versiyonu.
Ash


18

İstersen bunu rastgele sayılar için yaratırım . bu, Int ve Double, Float sayısının uzantısıdır

/**
    Arc Random for Double and Float
*/
public func arc4random <T: IntegerLiteralConvertible> (type: T.Type) -> T {
    var r: T = 0
    arc4random_buf(&r, UInt(sizeof(T)))
    return r
}
public extension Int {
    /**
    Create a random num Int
    :param: lower number Int
    :param: upper number Int
    :return: random number Int
    By DaRkDOG
    */
    public static func random (#lower: Int , upper: Int) -> Int {
        return lower + Int(arc4random_uniform(upper - lower + 1))
    }

}
public extension Double {
    /**
    Create a random num Double
    :param: lower number Double
    :param: upper number Double
    :return: random number Double
    By DaRkDOG
    */
    public static func random(#lower: Double, upper: Double) -> Double {
        let r = Double(arc4random(UInt64)) / Double(UInt64.max)
        return (r * (upper - lower)) + lower
    }
}
public extension Float {
    /**
    Create a random num Float
    :param: lower number Float
    :param: upper number Float
    :return: random number Float
    By DaRkDOG
    */
    public static func random(#lower: Float, upper: Float) -> Float {
        let r = Float(arc4random(UInt32)) / Float(UInt32.max)
        return (r * (upper - lower)) + lower
    }
}

KULLANIM:

let randomNumDouble = Double.random(lower: 0.00, upper: 23.50)
let randomNumInt = Int.random(lower: 56, upper: 992)
let randomNumInt =Float.random(lower: 6.98, upper: 923.09)

ikili operatör / iki Çift işlenen için uygulanamaz
Jason G

13

Swift 3/4:

func randomNumber(range: ClosedRange<Int> = 1...6) -> Int {
    let min = range.lowerBound
    let max = range.upperBound
    return Int(arc4random_uniform(UInt32(1 + max - min))) + min
}

8

Bunun nedeni arc4random_uniform () aşağıdaki gibi tanımlanmıştır:

func arc4random_uniform(_: UInt32) -> UInt32

Girdi olarak bir UInt32 alır ve bir UInt32 çıkarır. Bir dizi değeri iletmeye çalışıyorsunuz. arc4random_uniform size 0 ile geçirdiğiniz sayı (yalnızca) arasında rastgele bir sayı verir, bu nedenle örneğin, [-50, 50]kullanabileceğiniz gibi -50 ile 50 arasında rastgele bir sayı bulmak istediysenizarc4random_uniform(101) - 50


Sky sorumu mükemmel bir şekilde cevapladı Aynı şeyi söylediğinize inanıyorum, çok teşekkür ederim, dice1,2 = arc4random_uniform (6) +1 ayarlayarak gerçekten de aralığı 1-6 olarak ayarladığımı doğrulayabilirim Bunu bir iddiayla test ettim: D
arcreigh

6

@DaRk -_- D0G'nin yanıtını Swift 2.0 ile çalışacak şekilde değiştirdim

/**
Arc Random for Double and Float
*/
public func arc4random <T: IntegerLiteralConvertible> (type: T.Type) -> T {
    var r: T = 0
    arc4random_buf(&r, sizeof(T))
    return r
}
public extension Int {
    /**
    Create a random num Int
    :param: lower number Int
    :param: upper number Int
    :return: random number Int
    By DaRkDOG
    */
    public static func random (lower: Int , upper: Int) -> Int {
        return lower + Int(arc4random_uniform(UInt32(upper - lower + 1)))
    }

}
public extension Double {
    /**
    Create a random num Double
    :param: lower number Double
    :param: upper number Double
    :return: random number Double
    By DaRkDOG
    */
    public static func random(lower: Double, upper: Double) -> Double {
        let r = Double(arc4random(UInt64)) / Double(UInt64.max)
        return (r * (upper - lower)) + lower
    }
}
public extension Float {
    /**
    Create a random num Float
    :param: lower number Float
    :param: upper number Float
    :return: random number Float
    By DaRkDOG
    */
    public static func random(lower: Float, upper: Float) -> Float {
        let r = Float(arc4random(UInt32)) / Float(UInt32.max)
        return (r * (upper - lower)) + lower
    }
}

Burada en hızlı çözüm! Çok teşekkürler!
Andrew


3

Hızla ...

Bu kapsayıcıdır, arama random(1,2)1 veya 2 döndürür, Bu da negatif sayılarla çalışacaktır.

    func random(min: Int, _ max: Int) -> Int {
        guard min < max else {return min}
        return Int(arc4random_uniform(UInt32(1 + max - min))) + min
    }

3

Cevap sadece 1 satır kodudur:

let randomNumber = arc4random_uniform(8999) + 1000 //for 4 digit random number
let randomNumber = arc4random_uniform(899999999) + 100000000 //for 9 digit random number
let randomNumber = arc4random_uniform(89) + 10    //for 2 digit random number
let randomNumber = arc4random_uniform(899) + 100  //for 3 digit random number

Alternatif çözüm şudur:

    func generateRandomNumber(numDigits: Int) -> Int{
    var place = 1
    var finalNumber = 0;
    var finanum = 0;
    for var i in 0 ..< numDigits {
        place *= 10
        let randomNumber = arc4random_uniform(10)         
        finalNumber += Int(randomNumber) * place
        finanum = finalNumber / 10
           i += 1
    }
    return finanum
}

Dezavantajı bu sayı 0'dan başlayamaz.


2

Swift 4.2'den beri:

Int {    
    public static func random(in range: ClosedRange<Int>) -> Int
    public static func random(in range: Range<Int>) -> Int
}

Gibi kullanılır:

Int.random(in: 2...10)

2

Düzenleme: Swift 4.2+ şimdi bunu sağlar:

(100...200).randomElement()

Genişletmek benim için deyimsel Range:

public extension Range where Bound == Int {
    var random: Int {
        return lowerBound + Int(arc4random_uniform(UInt32(upperBound - lowerBound)))
    }
}

public extension ClosedRange where Bound == Int {
    var random: Int {
        return lowerBound + Int(arc4random_uniform(UInt32(upperBound - lowerBound + 1)))
    }
}

Kullanımda:

let foo = (100..<600).random

Muhtemelen üslupla ilgili bir şey. Her iki yöntemin de doğasında bir avantajı yoktur, sadece daha rahat hissettiğiniz şeydir.
Ash

1
Bu “üslup” düşünün insanlar için ben onlar için bir dil önerisi var: C. İyi eğlenceler!
mxcl

Eminim birisi bunu 3 yıl önce yapmıştı :) stackoverflow.com/questions/34712453/…
Leo Dabus

1

Aşağıdaki kodu kullanarak rastgele bir sayı oluşturmayı başarıyla başardım:

var coin = arc4random_uniform(2) + 1

Umarım bu size yardımcı olabilir.


0

Swift 3 Xcode Beta 5 Çözümü. Ted van Gaalen Cevabına göre.

extension Int
  {
     static func random(range: Range<Int> ) -> Int
    {
        var offset = 0

        if range.lowerBound < 0   // allow negative ranges
        {
            offset = Swift.abs(range.lowerBound)
        }

        let mini = UInt32(range.lowerBound + offset)
        let maxi = UInt32(range.upperBound   + offset)

        return Int(mini + arc4random_uniform(maxi - mini)) - offset
    }
}

0

var rangeFromLimits = arc4random_uniform ((UPPerBound - LOWerBound) + 1)) + LOWerBound;


0

umarım bu işe yarar. arc4random_uniform () için aralık arasında rastgele sayı yapmak?

var randomNumber = Int(arc4random_uniform(6))
print(randomNumber)

0

Muhtemelen Range, Swift 4 / Xcode 9+ kullanarak Ted van Gaalen'in cevabından bu biraz güncellenmiş uzantı sürümünü faydalı bulabilirsiniz :

extension CountableClosedRange where Bound == Int {
    var randomFromRange: Bound {
        get {
            var offset = 0
            if lowerBound < 0 {
                offset = abs(lowerBound)
            }
            let mini = UInt32(lowerBound + offset)
            let maxi = UInt32(upperBound + offset)
            return Int(mini + arc4random_uniform(maxi - mini)) - offset
        }
    }
}

let n = (-1000 ... 1000).randomFromRange
print(n)

Ya da açık ve kapalı aralıkları desteklemek için bu biraz "hacky" çözüm:

extension CountableRange where Bound == Int {
    var randomFromRange: Bound {
        return uniformRandom(from: lowerBound, to: upperBound)
    }
}

extension CountableClosedRange where Bound == Int {
    var randomFromRange: Bound {
        return uniformRandom(from: lowerBound, to: upperBound - 1)
    }
}

func uniformRandom(from: Int, to: Int) -> Int {
    var offset = 0
    if from < 0 {
        offset = abs(from)
    }
    let mini = UInt32(from + offset)
    let maxi = UInt32(to + offset)
    return Int(mini + arc4random_uniform(maxi - mini)) - offset
}

Her iki tür aralığa aynı anda özellik eklemenin bir yolu olup olmadığından emin değilim.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.