web-dev-qa-db-ja.com

Swiftの範囲内でランダムな整数を生成する最も簡単な方法は何ですか?

これまでに考案した方法は次のとおりです。

func randRange (lower : Int , upper : Int) -> Int {
    let difference = upper - lower
    return Int(Float(Rand())/Float(Rand_MAX) * Float(difference + 1)) + lower
}

これにより、下限と上限の間のランダムな整数が生成されます。

21
RonH

これはやや軽量なバージョンです。

func randRange (lower: Int , upper: Int) -> Int {
    return lower + Int(arc4random_uniform(UInt32(upper - lower + 1)))
}

この関数が符号なしの値でのみ機能する場合、これはさらに単純化できます。

func randRange (lower: UInt32 , upper: UInt32) -> UInt32 {
    return lower + arc4random_uniform(upper - lower + 1)
}

または、範囲をパラメータとして使用するというAntonの(あなたのための+1)優れたアイデアに従ってください。

func random(range: Range<UInt32>) -> UInt32 {
    return range.startIndex + arc4random_uniform(range.endIndex - range.startIndex + 1)
}
51
Jean Le Moignan

コメントの提案に従ってモジュロバイアスを削除するように編集されました。 (ありがとう!)

1..100または1 ... 100(上限を含むまたは除外する)を指定できるため、これを行うための適切な方法は、Swiftの範囲を使用して境界を定義することであると思います。私がこれまでに思いついた最高のものは:

import Foundation // needed for Rand()

func randInRange(range: Range<Int>) -> Int {
    // arc4random_uniform(_: UInt32) returns UInt32, so it needs explicit type conversion to Int
    // note that the random number is unsigned so we don't have to worry that the modulo
    // operation can have a negative output
    return  Int(arc4random_uniform(UInt32(range.endIndex - range.startIndex))) + range.startIndex
}

// generate 10 random numbers between -1000 and 999
for _ in 0...100 {
    randInRange(-1000...1000)
}

Rangeで拡張機能を使用しようとしましたが、Range <T where T:Int>を拡張することはできません。 (1..100).Rand()のような構文を取得できればさらに良いでしょう。

14
Anton Tcholakov

拡張機能を使用している場合:

extension CountableClosedRange where Bound == Int {
    var randomValue: Int {
        return lowerBound + Int(arc4random_uniform(UInt32(upperBound - lowerBound)))
    }
}

extension CountableRange where Bound == Int {
    var randomValue: Int {
        return lowerBound + Int(arc4random_uniform(UInt32(upperBound - lowerBound)))
    }
}

(0...6).randomValue
(0..<7).randomValue
2
lucamegh