Swift aléatoire flottant entre 0 et 1

Exécution de Xcode6-Beta4, dans la version bêta publique d’OSX Yosemite.

J’essaie d’obtenir un flottement aléatoire entre 0 et 1 mais je n’arrive pas à faire fonctionner les conversions de type.

func randomCGFloat() -> CGFloat { return CGFloat(arc4random()) / UINT32_MAX } 

Je reçois un ‘CGFloat’ n’est pas convertible en erreur ‘UInt8’

Essayez d’initialiser le diviseur en tant que flotteur, a la:

 CGFloat(Float(arc4random()) / Float(UINT32_MAX)) 

Ceci est une extension pour les nombres aléatoires de Int, Double, Float, CGFloat

Swift 3 & 4 syntaxe

 import Foundation import CoreGraphics // MARK: Int Extension public extension Int { /// Returns a random Int point number between 0 and Int.max. public 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 public 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 public 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. public 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 public 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. public 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 public 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. public 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. public 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 public static func random(min: CGFloat, max: CGFloat) -> CGFloat { return CGFloat.random * (max - min) + min } } 

Utilisation :

 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) 

Mise à jour de la réponse de Sandy Chapman pour 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 } } 

Maintenant, vous pouvez dire des choses comme (-1.0...1.0).random() .

EDIT je pense aujourd’hui (Swift 4) J’écrirais que quelque chose comme ça:

 extension ClosedRange where Bound : FloatingPoint { public func random() -> Bound { let max = UInt32.max return Bound(arc4random_uniform(max)) / Bound(max) * (upperBound - lowerBound) + lowerBound } } 

REMARQUE Swift 4.2 introduit la génération de nombres aléatoires native et tout cela devient sans object.

Ici, le framework fait un bon travail pour générer des données de nombres aléatoires dans 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 } } 

Voici une extension du type IntervalType pour faire ceci:

 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 } } 

Avec cette extension, vous pouvez utiliser la syntaxe d’intervalle pour générer un intervalle puis obtenir une valeur aléatoire dans cet intervalle:

 (0.0...1.0).random() 

Une addition

Si vous souhaitez faire la même chose pour Int s, vous pouvez utiliser l’extension suivante sur le protocole 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 n’utilise pas IntervalType . Ils utilisent Range place. L’avantage de le faire sur le type CollectionType est qu’il est automatiquement Array types Dictionary et Array .

Exemples:

 (0...10).random() // Ex: 6 ["A", "B", "C"].random() // Ex: "B" ["X":1, "Y":2, "Z":3].random() // Ex: (.0: "Y", .1: 2) 

Ce que jmduke a suggéré semble fonctionner dans Playground avec un petit changement dans la fonction:

 func randomCGFloat() -> Float { return Float(arc4random()) / Float(UInt32.max) } 

et la raison pour laquelle de la doc rapide et comme noté par drewag: conversion de type doit être explicite, l’exemple dans la doc est:

 let three = 3 let pointOneFourOneFiveNine = 0.14159 let pi = Double(three) + pointOneFourOneFiveNine // pi equals 3.14159, and is inferred to be of type Double 

swift 4.2:

 let randomFloat = Float.random(in: 0..<1) 

Détails

Xcode: 9.2, Swift 4

Solution

 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 } } 

Usage

 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))") 

Échantillon complet

 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(min: T, max: T, random: T) { let result = "\(T.self) rand[\(min), \(max)] = \(random)" print(result) } func floatSample(min: T, max: T, precision: Int) { printResult(min: min, max: max, random: T.rand(min, max, precision: precision)) } func intSample(min: T, max: T) { printResult(min: min, max: max, random: T.rand(min, max)) } 

Résultats

entrer la description de l'image ici

 drand48() 

Au cas où vous auriez besoin de [Double]. Entre 0 et 1. C’est tout.

Basé sur la réponse de YannickSteph

Pour que cela fonctionne pour tout type de virgule flottante, comme Double , Float , CGFloat , etc., vous pouvez créer une extension pour le type 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 } }