在Swift中,我试图获取一个0到1之间的随机浮点数,但是似乎无法进行类型转换。
func randomCGFloat() -> CGFloat {
return CGFloat(arc4random()) / UINT32_MAX
}
我遇到了一个 'CGFloat' 无法转换为 'UInt8' 的错误。
正在运行 Xcode 6。
在Swift中,我试图获取一个0到1之间的随机浮点数,但是似乎无法进行类型转换。
func randomCGFloat() -> CGFloat {
return CGFloat(arc4random()) / UINT32_MAX
}
我遇到了一个 'CGFloat' 无法转换为 'UInt8' 的错误。
正在运行 Xcode 6。
这是针对 Int、Double、Float、CGFloat 的随机数 扩展。
Swift 3、4、5 语法。
import Foundation
import CoreGraphics
// MARK: Int Extension
public extension Int {
/// Returns a random Int point number between 0 and Int.max.
static var random: Int {
return Int.random(n: Int.max)
}
/// Random integer between 0 and n-1.
///
/// - Parameter n: Interval max
/// - Returns: Returns a random Int point number between 0 and n max
static func random(n: Int) -> Int {
return Int(arc4random_uniform(UInt32(n)))
}
/// Random integer between min and max
///
/// - Parameters:
/// - min: Interval minimun
/// - max: Interval max
/// - Returns: Returns a random Int point number between 0 and n max
static func random(min: Int, max: Int) -> Int {
return Int.random(n: max - min + 1) + min
}
}
// MARK: Double Extension
public extension Double {
/// Returns a random floating point number between 0.0 and 1.0, inclusive.
static var random: Double {
return Double(arc4random()) / 0xFFFFFFFF
}
/// Random double between 0 and n-1.
///
/// - Parameter n: Interval max
/// - Returns: Returns a random double point number between 0 and n max
static func random(min: Double, max: Double) -> Double {
return Double.random * (max - min) + min
}
}
// MARK: Float Extension
public extension Float {
/// Returns a random floating point number between 0.0 and 1.0, inclusive.
static var random: Float {
return Float(arc4random()) / 0xFFFFFFFF
}
/// Random float between 0 and n-1.
///
/// - Parameter n: Interval max
/// - Returns: Returns a random float point number between 0 and n max
static func random(min: Float, max: Float) -> Float {
return Float.random * (max - min) + min
}
}
// MARK: CGFloat Extension
public extension CGFloat {
/// Randomly returns either 1.0 or -1.0.
static var randomSign: CGFloat {
return (arc4random_uniform(2) == 0) ? 1.0 : -1.0
}
/// Returns a random floating point number between 0.0 and 1.0, inclusive.
static var random: CGFloat {
return CGFloat(Float.random)
}
/// Random CGFloat between 0 and n-1.
///
/// - Parameter n: Interval max
/// - Returns: Returns a random CGFloat point number between 0 and n max
static func random(min: CGFloat, max: CGFloat) -> CGFloat {
return CGFloat.random * (max - min) + min
}
}
用途:
let randomNumDouble = Double.random(min: 0.00, max: 23.50)
let randomNumInt = Int.random(min: 56, max: 992)
let randomNumFloat = Float.random(min: 6.98, max: 923.09)
let randomNumCGFloat = CGFloat.random(min: 6.98, max: 923.09)
return Float(arc4random()) / 0xFFFFFFFF
现在会出现警告:'4294967295' is not exactly representable as 'Float'; it becomes '4294967296'
。有什么解决这个警告的想法吗?我想改为除以 Float(UInt32.max)
。 - peacetype尝试将除数也初始化为浮点数,如下所示:
CGFloat(Float(arc4random()) / Float(UINT32_MAX))
Float
- 只需使用 CGFloat(arc4random()) / CGFloat(UInt32.max)
。 - HamishSwift 4.2:
let randomFloat = Float.random(in: 0..<1)
更新 Sandy Chapman 的回答,以适应 Swift 3:
extension ClosedRange where Bound : FloatingPoint {
public func random() -> Bound {
let range = self.upperBound - self.lowerBound
let randomValue = (Bound(arc4random_uniform(UINT32_MAX)) / Bound(UINT32_MAX)) * range + self.lowerBound
return randomValue
}
}
现在你可以像这样说:(-1.0...1.0).random()
。
编辑 我认为今天(Swift 4)我会这样写:
extension ClosedRange where Bound : FloatingPoint {
public func random() -> Bound {
let max = UInt32.max
return
Bound(arc4random_uniform(max)) /
Bound(max) *
(upperBound - lowerBound) +
lowerBound
}
}
注意,Swift 4.2引入了本地随机数生成,因此所有这些都变得不重要了。
这个框架在Swift中生成随机数数据方面做得很好:https://github.com/thellimist/SwiftRandom/blob/master/SwiftRandom/Randoms.swift
public extension Int {
/// SwiftRandom extension
public static func random(lower: Int = 0, _ upper: Int = 100) -> Int {
return lower + Int(arc4random_uniform(UInt32(upper - lower + 1)))
}
}
public extension Double {
/// SwiftRandom extension
public static func random(lower: Double = 0, _ upper: Double = 100) -> Double {
return (Double(arc4random()) / 0xFFFFFFFF) * (upper - lower) + lower
}
}
public extension Float {
/// SwiftRandom extension
public static func random(lower: Float = 0, _ upper: Float = 100) -> Float {
return (Float(arc4random()) / 0xFFFFFFFF) * (upper - lower) + lower
}
}
public extension CGFloat {
/// SwiftRandom extension
public static func random(lower: CGFloat = 0, _ upper: CGFloat = 1) -> CGFloat {
return CGFloat(Float(arc4random()) / Float(UINT32_MAX)) * (upper - lower) + lower
}
}
以下是对IntervalType
类型的扩展,用于实现此功能:
extension IntervalType {
public func random() -> Bound {
let range = (self.end as! Double) - (self.start as! Double)
let randomValue = (Double(arc4random_uniform(UINT32_MAX)) / Double(UINT32_MAX)) * range + (self.start as! Double)
return randomValue as! Bound
}
}
使用此扩展,您可以使用间隔语法生成一个区间,然后在该区间内获取一个随机值:
(0.0...1.0).random()
加法
如果您想对 Int
进行相同的操作,那么可以使用以下扩展来实现 CollectionType
协议:
extension CollectionType {
public func random() -> Self._Element {
if let startIndex = self.startIndex as? Int {
let start = UInt32(startIndex)
let end = UInt32(self.endIndex as! Int)
return self[Int(arc4random_uniform(end - start) + start) as! Self.Index]
}
var generator = self.generate()
var count = arc4random_uniform(UInt32(self.count as! Int))
while count > 0 {
generator.next()
count = count - 1
}
return generator.next() as! Self._Element
}
}
Int
不使用 IntervalType
,而是使用 Range
。在 CollectionType
类型上这么做的好处是它会自动应用到 Dictionary
和 Array
类型。
示例:
(0...10).random() // Ex: 6
["A", "B", "C"].random() // Ex: "B"
["X":1, "Y":2, "Z":3].random() // Ex: (.0: "Y", .1: 2)
Int
、Dictionary
和Array
上使用.random()
的细节。 - Sandy ChapmanSwift 5
let randomFloat = CGFloat.random(in: 0...1)
看起来jmduke建议的方法在Playground中是有效的,只需要对函数进行一些小修改:
func randomCGFloat() -> Float {
return Float(arc4random()) / Float(UInt32.max)
}
从Swift文档和drewag的注释可以得知,类型转换必须是显式的。文档中给出的示例如下:
let three = 3
let pointOneFourOneFiveNine = 0.14159
let pi = Double(three) + pointOneFourOneFiveNine
// pi equals 3.14159, and is inferred to be of type Double
drand48()
如果需要[双精度],它的范围是0到1。就是这样。
srand48(Int(Date().timeIntervalSince1970))
。 - AlKozin基于YannickSteph的答案
为了使其适用于任何浮点类型,例如Double
、Float
、CGFloat
等,您可以为BinaryFloatingPoint
类型创建一个扩展:
extension BinaryFloatingPoint {
/// Returns a random floating point number between 0.0 and 1.0, inclusive.
public static var random: Self {
return Self(arc4random()) / 0xFFFFFFFF
}
/// Random double between 0 and n-1.
///
/// - Parameter n: Interval max
/// - Returns: Returns a random double point number between 0 and n max
public static func random(min: Self, max: Self) -> Self {
return Self.random * (max - min) + min
}
}