В Swift я пытаюсь получить случайное число с плавающей запятой между 0 и 1, но я не могу заставить работать преобразования типов.
func randomCGFloat() -> CGFloat {
return CGFloat(arc4random()) / UINT32_MAX
}
Я получаю сообщение об ошибке "CGFloat" не преобразовывается в "UInt8"
Запуск Xcode 6.
swift
random
arc4random
cgfloat
Joe_Schmoe
источник
источник
Ответы:
Попробуйте также инициализировать делитель как float, а-ля:
CGFloat(Float(arc4random()) / Float(UINT32_MAX))
источник
Float
- простоCGFloat(arc4random()) / CGFloat(UInt32.max)
.Это расширение для случайных чисел из 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)
вместо этого разделить на .быстрый 4.2:
let randomFloat = Float.random(in: 0..<1)
источник
Обновление ответа Сэнди Чепмена для 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 } }
источник
Generic iOS device
. 0xffffffff не помещается в Int. Попробуйте вместо этого CGFloat (UInt32.max)Ниже приведено расширение
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
s, вы можете использовать следующее расширение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
s не используйте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)
источник
.random()
наInt
с,Dictionary
S иArray
SSwift 5
let randomFloat = CGFloat.random(in: 0...1)
источник
То, что предложил jmduke, похоже, работает в Playground с небольшим изменением функции:
func randomCGFloat() -> Float { return Float(arc4random()) / Float(UInt32.max) }
и причина, по которой из быстрого документа и, как было отмечено 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
источник
Если вам нужен [Double]. Между 0 и 1. Вот и все.
источник
На основе ответа Янника Стефа
Для того, чтобы сделать его работу для любого типа с плавающей точкой, как
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 } }
источник
Детали
Xcode: 9.2, Swift 4
Решение
extension BinaryInteger { static func rand(_ min: Self, _ max: Self) -> Self { let _min = min let difference = max+1 - _min return Self(arc4random_uniform(UInt32(difference))) + _min } } extension BinaryFloatingPoint { private func toInt() -> Int { // https://stackoverflow.com/q/49325962/4488252 if let value = self as? CGFloat { return Int(value) } return Int(self) } static func rand(_ min: Self, _ max: Self, precision: Int) -> Self { if precision == 0 { let min = min.rounded(.down).toInt() let max = max.rounded(.down).toInt() return Self(Int.rand(min, max)) } let delta = max - min let maxFloatPart = Self(pow(10.0, Double(precision))) let maxIntegerPart = (delta * maxFloatPart).rounded(.down).toInt() let randomValue = Int.rand(0, maxIntegerPart) let result = min + Self(randomValue)/maxFloatPart return Self((result*maxFloatPart).toInt())/maxFloatPart } }
Применение
print("\(Int.rand(1, 20))") print("\(Float.rand(5.231233, 44.5, precision: 3))") print("\(Double.rand(5.231233, 44.5, precision: 4))") print("\(CGFloat.rand(5.231233, 44.5, precision: 6))")
Полный образец
import Foundation import CoreGraphics func run() { let min = 2.38945 let max = 2.39865 for _ in 0...100 { let precision = Int.rand(0, 5) print("Precision: \(precision)") floatSample(min: Float(min), max: Float(max), precision: precision) floatSample(min: Double(min), max: Double(max), precision: precision) floatSample(min: CGFloat(min), max: CGFloat(max), precision: precision) intSample(min: Int(1), max: Int(10000)) print("") } } private func printResult<T: Comparable>(min: T, max: T, random: T) { let result = "\(T.self) rand[\(min), \(max)] = \(random)" print(result) } func floatSample<T: BinaryFloatingPoint>(min: T, max: T, precision: Int) { printResult(min: min, max: max, random: T.rand(min, max, precision: precision)) } func intSample<T: BinaryInteger>(min: T, max: T) { printResult(min: min, max: max, random: T.rand(min, max)) }
Полученные результаты
источник