我意识到Swift书籍提供了一个随机数生成器的实现。复制和粘贴这个实现是最佳实践吗?或者有没有这样的库,我们现在就可以使用?
当前回答
下面的代码将产生一个0到255之间的安全随机数:
extension UInt8 {
public static var random: UInt8 {
var number: UInt8 = 0
_ = SecRandomCopyBytes(kSecRandomDefault, 1, &number)
return number
}
}
你这样称呼它:
print(UInt8.random)
对于更大的数字,它会变得更复杂。 这是我能想到的最好的:
extension UInt16 {
public static var random: UInt16 {
let count = Int(UInt8.random % 2) + 1
var numbers = [UInt8](repeating: 0, count: 2)
_ = SecRandomCopyBytes(kSecRandomDefault, count, &numbers)
return numbers.reversed().reduce(0) { $0 << 8 + UInt16($1) }
}
}
extension UInt32 {
public static var random: UInt32 {
let count = Int(UInt8.random % 4) + 1
var numbers = [UInt8](repeating: 0, count: 4)
_ = SecRandomCopyBytes(kSecRandomDefault, count, &numbers)
return numbers.reversed().reduce(0) { $0 << 8 + UInt32($1) }
}
}
这些方法使用一个额外的随机数来确定有多少uint8将被用于创建随机数。最后一行将[UInt8]转换为UInt16或UInt32。
我不知道后两个是否还算真正的随机,但你可以根据自己的喜好进行调整:)
其他回答
从Swift 4.2开始
有一组新的api:
let randomIntFrom0To10 = Int.random(in: 0 ..< 10)
let randomDouble = Double.random(in: 1 ... 10)
所有数字类型现在都有random(in:)方法,该方法接受range。 它返回一个在该范围内均匀分布的数字。
博士TL;
那么,“好”的旧方法有什么错呢?
你必须使用导入的C api(它们在不同平台之间是不同的)。 而且……
如果我告诉你随机并不是那么随机呢?
如果您使用arc4random()(计算余数),如arc4random() % aNumber,结果不是均匀分布在0和aNumber之间。有一个问题叫做模偏倚。
模的偏见
通常,该函数生成一个0到MAX之间的随机数(取决于类型等)。举个简单的例子,假设最大的数字是7,你关心的是一个范围为0 ..< 2(或者间隔[0,3),如果你喜欢的话)。
单个数字的概率为:
0: 3/8 = 37.5% 1: 3/8 = 37.5% 2: 2/8 = 25%
换句话说,你更有可能得到0或1而不是2。 当然,请记住,这是非常简化的,MAX数字要高得多,使其更加“公平”。
Swift 4.2中的SE-0202 -随机统一解决了这个问题
我想补充现有的答案,在Swift书中的随机数生成器的例子是一个线性同余生成器(LCG),这是一个非常有限的一个,不应该除了必须平凡的例子,其中随机性的质量根本不重要。LCG永远不应该用于加密目的。
Arc4random()要好得多,可以用于大多数目的,但不应该用于加密目的。
如果您想要保证加密安全的内容,请使用SecCopyRandomBytes()。请注意,如果您将随机数生成器构建到某个东西中,其他人可能最终(错误地)将其用于加密目的(例如密码、密钥或盐生成),那么无论如何您都应该考虑使用SecCopyRandomBytes(),即使您的需要并不完全需要这样做。
我使用了下面的代码:
var k: Int = random() % 10;
下面的代码将产生一个0到255之间的安全随机数:
extension UInt8 {
public static var random: UInt8 {
var number: UInt8 = 0
_ = SecRandomCopyBytes(kSecRandomDefault, 1, &number)
return number
}
}
你这样称呼它:
print(UInt8.random)
对于更大的数字,它会变得更复杂。 这是我能想到的最好的:
extension UInt16 {
public static var random: UInt16 {
let count = Int(UInt8.random % 2) + 1
var numbers = [UInt8](repeating: 0, count: 2)
_ = SecRandomCopyBytes(kSecRandomDefault, count, &numbers)
return numbers.reversed().reduce(0) { $0 << 8 + UInt16($1) }
}
}
extension UInt32 {
public static var random: UInt32 {
let count = Int(UInt8.random % 4) + 1
var numbers = [UInt8](repeating: 0, count: 4)
_ = SecRandomCopyBytes(kSecRandomDefault, count, &numbers)
return numbers.reversed().reduce(0) { $0 << 8 + UInt32($1) }
}
}
这些方法使用一个额外的随机数来确定有多少uint8将被用于创建随机数。最后一行将[UInt8]转换为UInt16或UInt32。
我不知道后两个是否还算真正的随机,但你可以根据自己的喜好进行调整:)
我已经能够使用rand()来获得一个随机的CInt。你可以使用这样的方法使它成为Int型:
let myVar: Int = Int(rand())
你可以使用你最喜欢的C随机函数,并在需要时将值转换为Int。
推荐文章
- 如何删除默认的导航栏空间在SwiftUI导航视图
- 如何在Ruby中生成a和b之间的随机数?
- 如何在iOS中使用Swift编程segue
- Swift -整数转换为小时/分钟/秒
- 如何舍入一个双到最近的Int在迅速?
- 扁平化数组的数组在Swift
- Swift:声明一个空字典
- java.util.Random真的那么随机吗?我怎么能生成52!(阶乘)可能的序列?
- 从数组中随机选择一个元素
- 在Swift中如何调用GCD主线程上的参数方法?
- swift语言中的结构与类
- 我如何在Swift连接字符串?
- 我应该如何从字符串中删除所有的前导空格?- - - - - -斯威夫特
- 使用该集合的原因。种子功能
- Swift:理解// MARK