In Swift versuche ich, einen zufälligen Gleitkommawert zwischen 0 und 1 zu erhalten, aber ich kann die Typkonvertierungen anscheinend nicht zum Laufen bringen.
func randomCGFloat() -> CGFloat {
return CGFloat(arc4random()) / UINT32_MAX
}
Ich erhalte ein "CGFloat", das nicht in einen "UInt8" -Fehler konvertierbar ist
Ausführen von Xcode 6.
swift
random
arc4random
cgfloat
Joe_Schmoe
quelle
quelle
Antworten:
Versuchen Sie, den Divisor auch als Float zu initialisieren, a la:
CGFloat(Float(arc4random()) / Float(UINT32_MAX))
quelle
Float
- nurCGFloat(arc4random()) / CGFloat(UInt32.max)
.Dies ist eine Erweiterung für Zufallszahlen von Int, Double, Float, CGFloat
Schnelle 3 & 4 & 5-Syntax
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 } }
Verwenden :
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)
quelle
return Float(arc4random()) / 0xFFFFFFFF
jetzt eine Warnung aus :'4294967295' is not exactly representable as 'Float'; it becomes '4294967296'
. Irgendeine Idee, wie man diese Warnung löst? Ich denkeFloat(UInt32.max)
stattdessen zu teilen .schnell 4.2:
let randomFloat = Float.random(in: 0..<1)
quelle
Aktualisierung der Antwort von Sandy Chapman für 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 } }
Jetzt können Sie Dinge wie sagen
(-1.0...1.0).random()
.EDIT Ich denke heute (Swift 4) würde ich so etwas schreiben:
extension ClosedRange where Bound : FloatingPoint { public func random() -> Bound { let max = UInt32.max return Bound(arc4random_uniform(max)) / Bound(max) * (upperBound - lowerBound) + lowerBound } }
ANMERKUNG Swift 4.2 führt die native Zufallszahlengenerierung ein und all dies wird strittig.
quelle
Hier leistet Framework gute Arbeit beim Generieren von Zufallszahlendaten in 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 } }
quelle
Generic iOS device
. Das 0xffffffff passt nicht in ein Int. Versuchen Sie dies stattdessen CGFloat (UInt32.max)Unten finden Sie eine Erweiterung des
IntervalType
Typs dafür: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 } }
Mit dieser Erweiterung können Sie die Intervallsyntax verwenden, um ein Intervall zu generieren und dann einen zufälligen Wert in diesem Intervall abzurufen:
(0.0...1.0).random()
Zusatz
Wenn Sie dasselbe für
Int
s tun möchten, können Sie die folgende Erweiterung desCollectionType
Protokolls verwenden: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 benutze das nichtIntervalType
. Sie verwendenRange
stattdessen. Dies hat den Vorteil,CollectionType
dass der Typ automatisch auf die TypenDictionary
und übertragen wirdArray
.Beispiele:
(0...10).random() // Ex: 6 ["A", "B", "C"].random() // Ex: "B" ["X":1, "Y":2, "Z":3].random() // Ex: (.0: "Y", .1: 2)
quelle
.random()
vonInt
s,Dictionary
s undArray
s aktualisiertSwift 5
let randomFloat = CGFloat.random(in: 0...1)
quelle
Was jmduke vorgeschlagen hat, scheint auf dem Spielplatz mit einer kleinen Änderung der Funktion zu funktionieren:
func randomCGFloat() -> Float { return Float(arc4random()) / Float(UInt32.max) }
und der Grund, warum aus dem schnellen Dokument und wie von drawag angegeben: Typkonvertierung explizit sein muss, ist das Beispiel im Dokument:
let three = 3 let pointOneFourOneFiveNine = 0.14159 let pi = Double(three) + pointOneFourOneFiveNine // pi equals 3.14159, and is inferred to be of type Double
quelle
Falls Sie [Double] benötigen. Zwischen 0 und 1. Das ist alles.
quelle
Basierend auf der Antwort von YannickSteph
Um es Arbeit für jeden Gleitkommatyps, wie
Double
,Float
,CGFloat
usw., können Sie eine Erweiterung für den machenBinaryFloatingPoint
Typen: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 } }
quelle
Einzelheiten
Xcode: 9.2, Swift 4
Lösung
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 } }
Verwendung
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))")
Vollständige Probe
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)) }
Ergebnisse
quelle