在Swift范围内生成随机整数的最简单方法是什么?

时间:2020-12-08 14:03:04

The method I've devised so far is this:

到目前为止,我设计的方法是:

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

This generates random integers between lower and upper inclusive.

这在上下整数之间生成随机整数。

3 个解决方案

#1


49  

Here's a somewhat lighter version of it:

这里有一个比较轻的版本:

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

This can be simplified even further if you decide this function works with unsigned values only:

如果您决定此函数仅对无符号值起作用,则可以进一步简化:

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

Or, following Anton's (+1 for you) excellent idea of using a range as parameter:

或者,按照Anton(+1)的想法,使用range作为参数:

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

#2


14  

Edited to remove modulo bias per the suggestion in comments. (thanks!)

编辑以消除每个注释中的建议的模块化偏差。(谢谢!)

I think a neat way of doing this may be to use Swift's Range to define the bounds because then you can specify 1..100 or 1...100 (including or excluding the upper bound). The best I have come up with so far is:

我认为一个简单的方法是使用Swift的范围来定义边界,因为这样你就可以指定1。100或1…100(包括或不包括上限)。到目前为止,我想出的最好的办法是:

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)
}

I tried using an extension on Range but you cannot seem to extend Range< T where T: Int > specifically. It would be even better if you could get a syntax like (1..100).rand().

我试过在范围上使用扩展,但是你似乎不能扩展< T的范围,特别是T: Int >。如果您能够获得类似(1..100).rand()的语法,那就更好了。

#3


1  

If you are into extensions:

如果你进入扩展:

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

#1


49  

Here's a somewhat lighter version of it:

这里有一个比较轻的版本:

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

This can be simplified even further if you decide this function works with unsigned values only:

如果您决定此函数仅对无符号值起作用,则可以进一步简化:

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

Or, following Anton's (+1 for you) excellent idea of using a range as parameter:

或者,按照Anton(+1)的想法,使用range作为参数:

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

#2


14  

Edited to remove modulo bias per the suggestion in comments. (thanks!)

编辑以消除每个注释中的建议的模块化偏差。(谢谢!)

I think a neat way of doing this may be to use Swift's Range to define the bounds because then you can specify 1..100 or 1...100 (including or excluding the upper bound). The best I have come up with so far is:

我认为一个简单的方法是使用Swift的范围来定义边界,因为这样你就可以指定1。100或1…100(包括或不包括上限)。到目前为止,我想出的最好的办法是:

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)
}

I tried using an extension on Range but you cannot seem to extend Range< T where T: Int > specifically. It would be even better if you could get a syntax like (1..100).rand().

我试过在范围上使用扩展,但是你似乎不能扩展< T的范围,特别是T: Int >。如果您能够获得类似(1..100).rand()的语法,那就更好了。

#3


1  

If you are into extensions:

如果你进入扩展:

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