0 और 1 के बीच यादृच्छिक फ्लोट स्विफ्ट


82

स्विफ्ट में, मैं 0 और 1 के बीच एक यादृच्छिक फ्लोट प्राप्त करने की कोशिश कर रहा हूं, लेकिन मुझे काम करने के लिए प्रकार रूपांतरण प्राप्त नहीं हो सकता है।

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

मुझे 'CGFloat' मिल रहा है जो 'UInt8' त्रुटि के लिए परिवर्तनीय नहीं है

चल Xcode 6।


जवाबों:


103

भाजक को फ्लोट के रूप में आरम्भ करने का प्रयास करें:

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

धन्यवाद, मैंने CGFloat के साथ हर को कास्ट करने की कोशिश की थी और यह काम नहीं कर रहा था। लेकिन ऐसा लगता है कि पहले एक नाव पर चढ़ना, और फिर एक CGFloat के लिए काम करता है।
जो_शामो

2
कोई ज़रूरत नहीं है Float- बस के माध्यम से जाने के लिए CGFloat(arc4random()) / CGFloat(UInt32.max)
हमीश

@ जो_Schmoe यदि आप फ्लोट / CGFloat से नहीं जाते हैं, तो विभाजन एक छोटा पूर्णांक है जो एक बड़े पूर्णांक से विभाजित होता है, और हमेशा 0.
Teng L

4
लेकिन तेजी से 4.2 में बस का उपयोग करें: Float.random (में: 0 .. <1)
एंड्रयू पॉल सीमन्स

116

यह Int, Double, Float, CGFloat की यादृच्छिक संख्या के लिए विस्तार है

स्विफ्ट 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)

1
@DaRk -_- D0G मैं गणित को समझने की कोशिश कर रहा हूं। आप फ्लोट और डबल के लिए यादृच्छिक () के लिए 0xFFFFFFFF से विभाजित क्यों करते हैं?
क्रिस्टल

2
@EthanMick स्विफ्ट 2 लुक के लिए अपडेट जोड़ें;)
YannSteph

1
"गैर-फ़ंक्शन प्रकार के मूल्य को 'CGFloat' नहीं कह सकते।" CGFloat.random (मिनट: 0.1, अधिकतम: 10.1) का उपयोग करने की कोशिश करने पर त्रुटि दिखाई देती है
एंड्रयू

1
स्विफ्ट 4. के लिए किसी अपडेट की आवश्यकता नहीं है
RyuX51

1
@YannickSteph स्विफ्ट 5 और Xcode 10.2 के साथ, return Float(arc4random()) / 0xFFFFFFFFअब लाइन एक चेतावनी देती है '4294967295' is not exactly representable as 'Float'; it becomes '4294967296':। किसी भी विचार है कि चेतावनी को हल करने के लिए कैसे? मैं Float(UInt32.max)इसके बजाय विभाजित करने के लिए सोच रहा हूं ।
मोरपाइप


26

स्विफ्ट 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()

संपादित करें मुझे लगता है कि आज (स्विफ्ट 4) मैं लिखूंगा कि कुछ इस तरह है:

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

नोट स्विफ्ट 4.2 देशी यादृच्छिक संख्या पीढ़ी का परिचय देता है और यह सब मूट हो जाता है।


16

यहां स्विफ्ट में यादृच्छिक संख्या डेटा उत्पन्न करने पर रूपरेखा एक अच्छा काम करती है: 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)
neoneye

13

नीचे ऐसा करने के लिए 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()

इसके अलावा

यदि आप Ints के लिए भी ऐसा करना चाहते हैं , तो आप 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)

इनट्स के साथ-साथ मूल प्रश्न के लिए काम करने के लिए हमें यह कैसे मिलता है, लेकिन मूल प्रश्न पर एक अगला कदम लगता है, अगर हम इंटरवल
टाइप

1
@Joe_Schmoe: मैं का उपयोग करने पर विवरण के साथ मेरा उत्तर को नवीनीकृत किया है .random()पर Intहै, Dictionaryहै और Arrayएस
सैंडी फेरीवाला

मैं वास्तव में इस समाधान को पसंद करता हूं, लेकिन मैं बेहतर जेनेरिक प्रथाओं को शामिल करने के लिए अपडेट कर रहा हूं
tbondwilkinson

1
स्विफ्ट 3 में टूटा हुआ
मैट


6

जेमड्यूक ने सुझाव दिया कि वह खेल के मैदान में एक छोटे से बदलाव के साथ काम करे।

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

2
drand48()

मामले में आप की जरूरत है [डबल]। ० और १ के बीच।


1

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

1

विवरण

Xcode: 9.2, स्विफ्ट 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))
}

परिणाम

यहाँ छवि विवरण दर्ज करें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.