在 Swift 中调用不同程度的 arc4random 随机性?
Calling different extent of randomness of arc4random in Swift?
这可能是一个相当愚蠢的问题。我想知道在 Swift 中使用 arc4random_uniform 是否可以实现不同的 nuances/extent 随机性。这是一个例子:
let number = arc4random_uniform(10) + 1
print(number)
在这种情况下,将随机打印一个数字,从 1 到 10。但是有没有办法可以重复随机结果 2 到 3 次?结果将是这样的:
1, 1, 6, 6, 6, 3, 3, 8, 8, 9, 9, 9 ...
// 1) Randomly selected and 2) repeated 2 to 3 times randomly.
也许我可能会同时使用两个arc4random_uniform函数,但不能正确表达它们。如果您能给我一些建议,将不胜感激。 <3
关于随机数生成器的细微差别:请查看 GKRandomSource。
您在这里所做的并不是真正降低随机性,也不是修改随机数生成器中的参数。您只是将一个操作(带有一个随机参数)应用于一组随机整数。
extension Collection {
func duplicateItemsRandomly(range: CountableClosedRange<Int>) -> [Element] {
return self.reduce(into: [Element](), { (acc, element) in
let distance = UInt32(range.upperBound - range.lowerBound + 1)
let count = Int(arc4random_uniform(distance) + UInt32(range.lowerBound))
let result = Array.init(repeating: element, count: count)
acc.append(contentsOf: result)
})
}
}
let sequence = [1, 6, 3, 8, 9]
sequence.duplicateItemsRandomly(range: 2...3)
// [1, 1, 6, 6, 6, 3, 3, 3, 8, 8, 8, 9, 9, 9]
P.S:如果您在 Swift 4.2 中编写此代码,请使用 Int.random(in:)
。
为此,您需要生成两个值:随机 value
和 repeatCount
。此外,您需要记住这两个值,以便您可以重复 value
。您可以使用自定义 class:
class RandomWithRepeats {
var range: ClosedRange<Int>
var repeatRange: ClosedRange<Int>
var repeatCount = 0
var value = 0
init(range: ClosedRange<Int>, repeatRange: ClosedRange<Int>) {
self.range = range
self.repeatRange = repeatRange
}
// generate a random number in a range
// Just use Int.random(in:) with Swift 4.2 and later
func random(in range: ClosedRange<Int>) -> Int {
return Int(arc4random_uniform(UInt32(range.upperBound - range.lowerBound + 1))) + range.lowerBound
}
func nextValue() -> Int {
// if repeatCount is 0, its time to generate a new value and
// a new repeatCount
if repeatCount == 0 {
// For Swift 4.2, just use Int.random(in:) instead
value = self.random(in: range)
repeatCount = self.random(in: repeatRange)
}
repeatCount -= 1
return value
}
}
示例:
let rand = RandomWithRepeats(range: 1...10, repeatRange: 2...3)
// generate 20 random repeated numbers
for _ in 1...20
{
print(rand.nextValue(), terminator: " ")
}
6 6 6 8 8 8 10 10 10 2 2 9 9 5 5 8 8 8 5 5
我建议定制 Sequence
:
class RepeatingRandomSequence : Sequence {
let rangeLow, rangeSpan : UInt32
let repeatLow, repeatSpan : UInt32
init(range:Range<UInt32>, count:Range<UInt32>) {
rangeLow = range.lowerBound
rangeSpan = range.upperBound - range.lowerBound + 1
repeatLow = count.lowerBound
repeatSpan = count.upperBound - count.lowerBound + 1
}
func makeIterator() -> AnyIterator<UInt32> {
var count : UInt32 = 0
var value : UInt32 = 0
return AnyIterator {
if(count <= 0) {
count = arc4random_uniform(self.repeatSpan) + self.repeatLow
value = arc4random_uniform(self.rangeSpan) + self.rangeLow
}
defer { count = count - 1 }
return value
}
}
}
let sequence = RepeatingRandomSequence(range: 0..<10, count: 2..<3)
let randoms = sequence.makeIterator()
请注意,迭代器 randoms
现在使用 randoms.next()
生成无限的随机数序列,因为序列是无限的,所以很多东西不是特别有用,比如 sort
, map
,等等。但是您可以像这样使用它:
for value in random {
print(value)
if(value == 9) { // or any other termination condition
break
}
}
或者更传统地说,如:
(0..<10).forEach { _ in
print(String(describing: random.next()))
}
这可能是一个相当愚蠢的问题。我想知道在 Swift 中使用 arc4random_uniform 是否可以实现不同的 nuances/extent 随机性。这是一个例子:
let number = arc4random_uniform(10) + 1
print(number)
在这种情况下,将随机打印一个数字,从 1 到 10。但是有没有办法可以重复随机结果 2 到 3 次?结果将是这样的:
1, 1, 6, 6, 6, 3, 3, 8, 8, 9, 9, 9 ...
// 1) Randomly selected and 2) repeated 2 to 3 times randomly.
也许我可能会同时使用两个arc4random_uniform函数,但不能正确表达它们。如果您能给我一些建议,将不胜感激。 <3
关于随机数生成器的细微差别:请查看 GKRandomSource。
您在这里所做的并不是真正降低随机性,也不是修改随机数生成器中的参数。您只是将一个操作(带有一个随机参数)应用于一组随机整数。
extension Collection {
func duplicateItemsRandomly(range: CountableClosedRange<Int>) -> [Element] {
return self.reduce(into: [Element](), { (acc, element) in
let distance = UInt32(range.upperBound - range.lowerBound + 1)
let count = Int(arc4random_uniform(distance) + UInt32(range.lowerBound))
let result = Array.init(repeating: element, count: count)
acc.append(contentsOf: result)
})
}
}
let sequence = [1, 6, 3, 8, 9]
sequence.duplicateItemsRandomly(range: 2...3)
// [1, 1, 6, 6, 6, 3, 3, 3, 8, 8, 8, 9, 9, 9]
P.S:如果您在 Swift 4.2 中编写此代码,请使用 Int.random(in:)
。
为此,您需要生成两个值:随机 value
和 repeatCount
。此外,您需要记住这两个值,以便您可以重复 value
。您可以使用自定义 class:
class RandomWithRepeats {
var range: ClosedRange<Int>
var repeatRange: ClosedRange<Int>
var repeatCount = 0
var value = 0
init(range: ClosedRange<Int>, repeatRange: ClosedRange<Int>) {
self.range = range
self.repeatRange = repeatRange
}
// generate a random number in a range
// Just use Int.random(in:) with Swift 4.2 and later
func random(in range: ClosedRange<Int>) -> Int {
return Int(arc4random_uniform(UInt32(range.upperBound - range.lowerBound + 1))) + range.lowerBound
}
func nextValue() -> Int {
// if repeatCount is 0, its time to generate a new value and
// a new repeatCount
if repeatCount == 0 {
// For Swift 4.2, just use Int.random(in:) instead
value = self.random(in: range)
repeatCount = self.random(in: repeatRange)
}
repeatCount -= 1
return value
}
}
示例:
let rand = RandomWithRepeats(range: 1...10, repeatRange: 2...3)
// generate 20 random repeated numbers
for _ in 1...20
{
print(rand.nextValue(), terminator: " ")
}
6 6 6 8 8 8 10 10 10 2 2 9 9 5 5 8 8 8 5 5
我建议定制 Sequence
:
class RepeatingRandomSequence : Sequence {
let rangeLow, rangeSpan : UInt32
let repeatLow, repeatSpan : UInt32
init(range:Range<UInt32>, count:Range<UInt32>) {
rangeLow = range.lowerBound
rangeSpan = range.upperBound - range.lowerBound + 1
repeatLow = count.lowerBound
repeatSpan = count.upperBound - count.lowerBound + 1
}
func makeIterator() -> AnyIterator<UInt32> {
var count : UInt32 = 0
var value : UInt32 = 0
return AnyIterator {
if(count <= 0) {
count = arc4random_uniform(self.repeatSpan) + self.repeatLow
value = arc4random_uniform(self.rangeSpan) + self.rangeLow
}
defer { count = count - 1 }
return value
}
}
}
let sequence = RepeatingRandomSequence(range: 0..<10, count: 2..<3)
let randoms = sequence.makeIterator()
请注意,迭代器 randoms
现在使用 randoms.next()
生成无限的随机数序列,因为序列是无限的,所以很多东西不是特别有用,比如 sort
, map
,等等。但是您可以像这样使用它:
for value in random {
print(value)
if(value == 9) { // or any other termination condition
break
}
}
或者更传统地说,如:
(0..<10).forEach { _ in
print(String(describing: random.next()))
}