Swift随机数生成器,增量为25

时间:2014-12-31 21:49:39

标签: swift

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

如何将其修改为仅吐出25的增量?例如:

random(150...250) 

可能会给我150,175,200,225和250之间的任何内容。

我知道我可以检查它是否可以被25分割,但是谁知道它有多少次再次滚动&#39;找到一个被接受的号码。我正在寻找一些在代码中更优化和/或更清洁的东西。公平地说,我不知道arc4random_uniform函数有多快。

4 个答案:

答案 0 :(得分:2)

var num = 150 + ( random(0...4) * 25)

答案 1 :(得分:2)

func random25(min: Int, max: Int) -> Int {
    assert(max > min)
    let minIndex = min / 25
    let r = arc4random_uniform(UInt32(max / 25 - minIndex))
    return (Int(r) + minIndex) * 25
}

答案 2 :(得分:1)

func randomRange(range: Range<Int>, increment:Int ) -> Int {
    if Int(range.endIndex-1) % increment != 0  { return 0 }
    if increment > (Int(range.endIndex-1 ) - Int(range.startIndex )) { return 0 }
    if increment == 1 { return Int( arc4random_uniform( UInt32( Int(range.endIndex) - Int(range.startIndex) ) ) ) + Int(range.startIndex) }
    let numberOfRandomElements = ( ( Int(range.endIndex ) - Int(range.startIndex )) / increment ) + 1
    let randomAux = Int(arc4random_uniform(UInt32(numberOfRandomElements)))
    return  randomAux * increment + Int(range.startIndex)
}

randomRange(100...250, 25)
randomRange(100...250, 25)
randomRange(100...250, 25)
randomRange(100...250, 25)
randomRange(100...250, 25)
randomRange(100...250, 25)


randomRange(100...250, 5)
randomRange(100...250, 5)
randomRange(100...250, 5)
randomRange(100...250, 5)
randomRange(100...250, 5)
randomRange(100...250, 5)
randomRange(100...250, 5)

答案 3 :(得分:0)

这是一个灵活的实现,用于在范围内以恒定的间隔生成随机整数。在游乐场中运行它并使用菜单命令编辑器&gt;执行Playground以测试多个随机结果。

import Foundation

/// Returns an integer within the specified range, 
/// skipping values between intervals. Interval values are calculated 
/// starting from the range's startIndex for positive intervals 
/// and from the endIndex for negative intervals.

func randomInRange(range: Range<Int>, withInterval interval: Int = 1) -> Int {
    assert(interval != 0, "Function failed because increment argument is zero")
    let startIndex = range.startIndex
    let endIndex = range.endIndex
    assert(endIndex > startIndex, "Function failed because range's endIndex is not greater than startIndex")

    let penultimateIndex = endIndex - 1
    let possibilityCount = abs((penultimateIndex - startIndex) / interval) + 1
    let randomOffset = Int(arc4random_uniform(UInt32(possibilityCount))) * interval
    if interval > 0 {
        return startIndex + randomOffset
    } else {
        return penultimateIndex + randomOffset
    }
}

randomInRange(150...250, withInterval: 25) // As per OP's request

randomInRange(0..<2, withInterval: 1) // Only produces 0 or 1
randomInRange(0...2, withInterval: 1)
randomInRange(0...2) // Interval of 1 assumed
randomInRange(0...2, withInterval: 2)
randomInRange(0...2, withInterval: 3) // Only produces 0
randomInRange(0...2, withInterval: -3) // Only produces 2
randomInRange(0...4, withInterval: 2)
randomInRange(0...6, withInterval: 3)
randomInRange(0...6, withInterval: 4) // Only produces 0 or 4
randomInRange(0...6, withInterval: -4) // Only produces 6 or 2
randomInRange(1...10, withInterval: 3) // Produces 1, 4, 7, or 10
randomInRange(-3...3, withInterval: 3)
randomInRange(-7...5, withInterval: 3) // Produces values that are not multiples of the interval
randomInRange(0...100, withInterval: 25)
randomInRange(0...100, withInterval: -33) // Produces 100, 67, 34, or 1
randomInRange(0...0, withInterval: 1) // Only produces 0
// randomInRange(Range(start: 0, end: 0), withInterval: 1) // Assertion error for empty range
// randomInRange(0...100, withInterval: 0) // Assertion error for interval of 0

/// Returns an optional integer within the specified range, 
/// skipping values between intervals.  
/// If the range's startIndex and endIndex-1 are not multiples of the interval, 
/// the function adjusts these values in a narrower range with start and end indices at interval multiples. 
/// If no multiple of the interval exists in the given range, returns nil.

func randomInRange(range: Range<Int>, atMultipleOfInterval interval: Int) -> Int? {
    assert(interval != 0, "Function failed because increment argument is zero")
    let startIndex = range.startIndex
    let endIndex = range.endIndex
    assert(endIndex > startIndex, "Function failed because range's endIndex is not greater than startIndex")

    let penultimateIndex = endIndex - 1
    if (startIndex % interval != 0) || (penultimateIndex % interval != 0) {
        let adjustedStart = startIndex - startIndex % interval + interval
        let adjustedPenultimate: Int = penultimateIndex - penultimateIndex % interval
        if adjustedPenultimate >= adjustedStart {
            return randomInRange(adjustedStart...adjustedPenultimate, withInterval: interval)
        } else {
            return nil
        }
    } else {
        return randomInRange(startIndex...penultimateIndex, withInterval: interval)
    }
}

randomInRange(0...10, atMultipleOfInterval: 5)
randomInRange(2...4, atMultipleOfInterval: 5)  // Produces nil
randomInRange(7...13, atMultipleOfInterval: 10)
randomInRange(1...500, atMultipleOfInterval: 7)
randomInRange(300...300, atMultipleOfInterval: 25)

// With random range, return only random values that are multiples of the random interval
let interval = Int(arc4random_uniform(25)) + 1
var startIndex = Int(arc4random_uniform(500)) - 250
var penultimateIndex = startIndex + interval + Int(arc4random_uniform(250))
randomInRange(startIndex...penultimateIndex, atMultipleOfInterval: interval)