Arc4random_uniform () के लिए रेंज के बीच कोई यादृच्छिक संख्या कैसे बनाता है?


129

इसलिए इस कोडबिट में मेरा लक्ष्य बेतरतीब ढंग से दो पासा रोल करना है और जैसा कि हम सभी जानते हैं कि आपके नियमित मरने के केवल 6 पक्ष हैं इसलिए मैंने arc4random_uniform (UInt32) तक पहुंच के लिए फाउंडेशन का आयात किया। मैंने बेतरतीब ढंग से 0 प्राप्त करने से बचने के लिए (1..7) की सीमा का उपयोग करने का प्रयास किया लेकिन फिर भी एक त्रुटि हुई जिसे मुझे बहुत मज़ा नहीं आया। मैंने ऐसा करने की कोशिश की:

dice1 = arc4random_uniform(UInt32(1..7))

हालांकि वह लौट आया

आपूर्ति किए गए तर्कों को स्वीकार करने वाले 'init' के लिए अधिभार नहीं मिला

मुझे आशा है कि यह आपकी जानकारी के लिए पर्याप्त जानकारी है।

कृपया ध्यान दें कि मैं केवल खेल के मैदान में तेजी से अभ्यास करने के लिए कर रहा हूं। यह जरूरी नहीं है कि मैं सीखूं कि यह कैसे करना है; वास्तविक ऐप्स बनाने में कूदने से पहले यह सिर्फ मेरे साथ छेड़छाड़ है: डी

//imports random number function
import Foundation
//creates data storage for dice roll
var dice1: UInt32 = 0
var dice2: UInt32 = 0
//counter variable
var i = 0
//how many times snake eyes happens
var snakeeyes = 0
 //how many times a double is rolled
var `double` = 0
//rolls dice 100 times
while i < 100{
    //from here
    //sets dice roll

यह 'रेंज $ T3' की एक त्रुटि UInt32 के लिए परिवर्तनीय नहीं है

   dice1 = arc4random_uniform(1..7)
   dice2 = arc4random_uniform(1..7)
    //checks for snake eyes
    if dice1 == 1 && dice2 == 1 {
        snakeeyes = snakeeyes + 1

    }
    //checks for doubles
    if dice1 == dice2{
        `double` = `double` + 1
    }
    //increases counter
        i = i + 1
    //to here
}
println("You got Snake Eyes \(snakeeyes) times.")
println("You got Doubles, \(`double`) times.")

4
मेरा मानना ​​है कि आपको dice1 = arc4random_uniform(6) + 1रेंज 1 - 6. पाने के लिए करना चाहिए। मैं आईओएस ऑब्जेक्टिव सी नहीं करता हूं और न ही स्विफ्ट-लैंग्वेज का कोई ज्ञान है। यादृच्छिक विधि आपको 0 - 5, और + 1 1 - 6.
स्काई

1
रेंज एक ऑब्जेक्ट डेटा ही है, यह एक पूर्णांक डेटा नहीं है, इसीलिए आपको त्रुटि तब मिल रही है जब तर्क केवल (UInt32) में लेता है -u_int32_t arc4random_uniform(u_int32_t upper_bound);
आकाश

अहा! शुक्रिया आकाश! परीक्षण करने के लिए एक जोर दिया था अगर यह कम हो रहा था तो 0 और यह पुष्टि कर सकता है कि वास्तव में मुझे इसकी आवश्यकता क्या थी, इसलिए मैं इसे एक उत्तर के रूप में देख सकता हूं!
चाप्रे

प्रायिकता = Int (arc4random_uniform (UInt32 (कुल))) - यदि आपके पास कई कास्टिंग शिकायतें हैं जो बकवास हैं (क्योंकि टाइपरहेड / हेडर कार्यात्मक नहीं हैं)
bshirley

इसे Swift 4.2 के साथ शुरू करने के लिए बनाया गया है जैसा कि नीचे stackoverflow.com/a/50696901/1148030
पीटर लैम्बबर्ग

जवाबों:


260

मेरा मानना ​​है कि आपको करना चाहिए

dice1 = arc4random_uniform(6) + 1;

रेंज 1 पाने के लिए - 6. मैं iOS उद्देश्य C नहीं करता और न ही मुझे स्विफ्ट-लैंग्वेज पर कोई ज्ञान है। यादृच्छिक विधि को 0 और 5 के बीच मान वापस करना चाहिए, और + 1 इसे 1 और 6 के बीच का मान देगा।

अगर आपको 10 - 30 के बीच सीमा की आवश्यकता है तो बस करें

int random = arc4random_uniform(21) + 10;

2
@ जोसेमिथ आप इस पर बिल्कुल सही हैं, यह 10 से 30 के बीच की सीमा को वापस करने के लिए arc4random_uniform (21) +10 होना चाहिए क्योंकि ऊपरी बाउंड समावेशी नहीं है। भाग "arc4random_uniform (20) +10" सामुदायिक संपादन और वोटों पर आधारित है।
स्काई

हां, मैंने अभी-अभी परीक्षण किया है और एक यादृच्छिक रंग प्राप्त करने के लिए (यानी 0 से 255 के बीच एक यादृच्छिक मान चाहा), मैंने उपयोग किया: "arc4random_uniform (256) + 0"
क्रिस एलिन्सन

91

मैंने एक Int प्रकार का विस्तार किया है। खेल के मैदान में इसका परीक्षण किया, आशा है कि यह उपयोगी है। यह नकारात्मक सीमाओं को भी स्वीकार करता है:

extension Int
{
    static func random(range: Range<Int> ) -> Int
    {
        var offset = 0

        if range.startIndex < 0   // allow negative ranges
        {
            offset = abs(range.startIndex)
        }

        let mini = UInt32(range.startIndex + offset)
        let maxi = UInt32(range.endIndex   + offset)

        return Int(mini + arc4random_uniform(maxi - mini)) - offset
    }
}

जैसे का उपयोग करें

var aRandomInt = Int.random(-500...100)  // returns a random number within the given range.

या इसे इस तरह संपत्ति के रूप में एक सीमा विस्तार के रूप में परिभाषित करें:

extension Range
{
    var randomInt: Int
    {
        get
        {
            var offset = 0

            if (startIndex as Int) < 0   // allow negative ranges
            {
                offset = abs(startIndex as Int)
            }

            let mini = UInt32(startIndex as Int + offset)
            let maxi = UInt32(endIndex   as Int + offset)

            return Int(mini + arc4random_uniform(maxi - mini)) - offset
        }
    }
}

// usage example: get an Int within the given Range:
let nr = (-1000 ... 1100).randomInt

6
आपका विस्तार सुंदर है: 3 स्विफ्ट का एक सच्चा उपयोग!
कलज़ेम

मुझे रेंज एक्सटेंशन पसंद है।
डेविड जेम्स

अच्छा उत्तर। मेरा केवल कहना है कि randomInt: Int या रेंज का कोई प्राकृतिक विस्तार नहीं है। मैं इसे केवल एक यूटिलिटी फ़ाइल में स्टैंड-अलोन फ़ंक्शन के रूप में जोड़ूंगा।
विंस ओ'सुल्लिवन

स्विफ्ट 3 के लिए अपडेट किए जाने की आवश्यकता है, रेंज की जगह ।startIndex को range.lowerBound के बजाय बदलें और EndIndex अब अपरबाउंड है
जोसेफ

62

कुछ अच्छे जवाब दिए, लेकिन मैं सिर्फ अपने व्यक्तिगत पसंदीदा स्विफ्ट यादृच्छिक पॉजिटिव फंक्शन को सकारात्मक पूर्णांक के लिए साझा करना चाहता था:

स्विफ्ट 2

func randomNumber(range: Range<Int> = 1...6) -> Int {
    let min = range.startIndex
    let max = range.endIndex
    return Int(arc4random_uniform(UInt32(max - min))) + min
}

स्विफ्ट 3

यहां स्विफ्ट 3 के लिए एक त्वरित अपडेट है और, एक बोनस के रूप में, यह अब किसी भी प्रकार के मूल्य के लिए काम करता है जो साइन इनइंटर प्रोटोकॉल के अनुरूप है - कोर डेटा अनुप्रयोगों के लिए बहुत अधिक सुविधाजनक है जिसे Int16, Int32 आदि को निर्दिष्ट करने की आवश्यकता है, यदि आप एक त्वरित नोट के रूप में, यदि आप वास्तव में, साथ ही अहस्ताक्षरित पूर्णांकों पर काम करने के लिए इसकी आवश्यकता है तो बस पूरे समारोह तो की जगह कॉपी SignedIntegerके साथ UnsignedIntegerऔर toIntMax()साथ toUIntMax()

func randomNumber<T : SignedInteger>(inRange range: ClosedRange<T> = 1...6) -> T {
    let length = (range.upperBound - range.lowerBound + 1).toIntMax()
    let value = arc4random().toIntMax() % length + range.lowerBound.toIntMax()
    return T(value)
}

स्विफ्ट 4

स्विफ्ट 4 में आईनेटमैक्स () को हटाने के लिए धन्यवाद, हमें अब एक सामान्य पूर्णांक प्रकार में परिवर्तित करने के विभिन्न साधनों का उपयोग करना होगा। इस उदाहरण में मैं Int64 का उपयोग कर रहा हूं जो मेरे उद्देश्यों के लिए काफी बड़ा है, लेकिन यदि आप अहस्ताक्षरित पूर्णांक का उपयोग कर रहे हैं या आपके पास एक Int128 या Int256 कस्टम प्रकार है, जिसका आपको उपयोग करना चाहिए।

public func randomNumber<T : SignedInteger>(inRange range: ClosedRange<T> = 1...6) -> T {
    let length = Int64(range.upperBound - range.lowerBound + 1)
    let value = Int64(arc4random()) % length + Int64(range.lowerBound)
    return T(value)
}

एक और, कुल रैंडम-फील के लिए, यहां एक एक्सटेंशन है जो किसी भी Collectionप्रकार की वस्तु से एक यादृच्छिक तत्व देता है । ध्यान दें कि इसके सूचकांक को उत्पन्न करने के लिए उपरोक्त फ़ंक्शन का उपयोग करता है ताकि आपको दोनों की आवश्यकता हो।

extension Collection {
    func randomItem() -> Self.Iterator.Element {
        let count = distance(from: startIndex, to: endIndex)
        let roll = randomNumber(inRange: 0...count-1)
        return self[index(startIndex, offsetBy: roll)]
    }
}

प्रयोग

randomNumber()

1 और 6 के बीच एक यादृच्छिक संख्या देता है।

randomNumber(50...100)

50 और 100 समावेशी के बीच एक संख्या देता है। स्वाभाविक रूप से आप 50 और 100 के मूल्यों को अपनी पसंद के साथ बदल सकते हैं।

स्विफ्ट 4.2

काश, मेरा सबसे अच्छा StackOverflow जवाब पिछले पर अप्रचलित किया गया है। अब आप Int.random(in: 1 ... 6)किसी दिए गए रेंज में एक यादृच्छिक संख्या उत्पन्न करने के लिए बस का उपयोग कर सकते हैं । पूर्णांक और फ्लोटिंग पॉइंट संख्या के अन्य रूपों के लिए भी काम करता है। संग्रह प्रकार अब भी प्रदान करते हैं shuffle()और randomElement()कार्य करते हैं । जब तक आप एक विशिष्ट रैंडमाइज़र प्रकार का उपयोग नहीं करना चाहते हैं, तब तक फैंसी रैंडमाइजेशन फ़ंक्शन की कोई आवश्यकता नहीं है।


1
मैंने इसे देखा और सोचा कि यह गलत होना चाहिए क्योंकि (अधिकतम - न्यूनतम) = 5, 0 से 4 की सीमा में एक यादृच्छिक पूर्णांक को जोड़ रहा है (साथ ही 1 से 5 बना रहा है)। लेकिन कोड को एक Xcode खेल के मैदान में डालने से स्पष्ट था कि यह काम करता था। कारण यह है कि अधिकतम वास्तव में 7 के बराबर है क्योंकि एंडइंडेक्स रिटर्न "संग्रह का पहला 'पिछले अंत की स्थिति है।" (जैसा कि Apple के प्रलेखन में कहा गया है)। तो, एक अच्छा जवाब और मेरे लिए एक उपयोगी सीखने का व्यायाम।
विंस ओ'सुलीवन

यह नकारात्मक पूर्णांक के साथ भी काम करता है। randomNumber(-3 ... -1)जब तक आपके पास पहले और बाद में रिक्त स्थान है, तब तक काम करता है ...। आप random(-3 ..< -1अंतिम संख्या को बाहर करने के लिए भी उपयोग कर सकते हैं ।
कार्टर मेडलिन

यदि आप यह काम गैर-पूर्णांक के साथ करना चाहते हैं ClosedInterval, Rangeतो इसके बजाय का उपयोग करें ।
कार्टर मेडलिन

मैं नहीं होगा अंतराल प्रकार स्विफ्ट 3 में पदावनत किए गए थे। कोड की कार्यक्षमता का विस्तार करने के लिए शायद जेनरिक का उपयोग करने का एक तरीका है, लेकिन मेरे पास जांच करने का समय, झुकाव या कारण नहीं है।
ऐश

1
वहाँ हम जाते हैं, कोड का एक सामान्यीकृत पूर्णांक संस्करण।
ऐश


18

यदि आप चाहते हैं कि मैं यादृच्छिक संख्या के लिए बनाऊं यह संख्या Int और डबल, फ्लोट का विस्तार है

/**
    Arc Random for Double and Float
*/
public func arc4random <T: IntegerLiteralConvertible> (type: T.Type) -> T {
    var r: T = 0
    arc4random_buf(&r, UInt(sizeof(T)))
    return r
}
public extension Int {
    /**
    Create a random num Int
    :param: lower number Int
    :param: upper number Int
    :return: random number Int
    By DaRkDOG
    */
    public static func random (#lower: Int , upper: Int) -> Int {
        return lower + Int(arc4random_uniform(upper - lower + 1))
    }

}
public extension Double {
    /**
    Create a random num Double
    :param: lower number Double
    :param: upper number Double
    :return: random number Double
    By DaRkDOG
    */
    public static func random(#lower: Double, upper: Double) -> Double {
        let r = Double(arc4random(UInt64)) / Double(UInt64.max)
        return (r * (upper - lower)) + lower
    }
}
public extension Float {
    /**
    Create a random num Float
    :param: lower number Float
    :param: upper number Float
    :return: random number Float
    By DaRkDOG
    */
    public static func random(#lower: Float, upper: Float) -> Float {
        let r = Float(arc4random(UInt32)) / Float(UInt32.max)
        return (r * (upper - lower)) + lower
    }
}

उपयोग :

let randomNumDouble = Double.random(lower: 0.00, upper: 23.50)
let randomNumInt = Int.random(lower: 56, upper: 992)
let randomNumInt =Float.random(lower: 6.98, upper: 923.09)

बाइनरी ऑपरेटर / को दो डबल ऑपरेंड पर लागू नहीं किया जा सकता
जेसन जी


8

ऐसा इसलिए है क्योंकि arc4random_uniform () को इस प्रकार परिभाषित किया गया है:

func arc4random_uniform(_: UInt32) -> UInt32

यह इनपुट के रूप में एक UInt32 लेता है, और UInt32 को बाहर निकालता है। आप इसे मानों की एक श्रेणी देने का प्रयास कर रहे हैं। arc4random_uniform आपको 0 और उस संख्या के बीच में एक यादृच्छिक संख्या देती है (विशेष रूप से), इसलिए यदि उदाहरण के लिए, आप -50 और 50 के बीच एक यादृच्छिक संख्या खोजना चाहते थे, जैसा कि [-50, 50]आप उपयोग कर सकते हैंarc4random_uniform(101) - 50


आकाश ने मेरे सवाल का पूरी तरह से जवाब दिया, मेरा मानना ​​है कि आप एक ही बात कह रहे हैं और साथ ही साथ बहुत-बहुत धन्यवाद भी पुष्टि कर सकते हैं कि dice1,2 = arc4random_uniform (6) +1 को सेट करके वास्तव में 1-6 तक सीमा निर्धारित की गई थी, मैंने इसे एक परख के साथ परीक्षण किया: डी
आर्कियो 3

6

मैंने स्विफ्ट 2.0 के साथ काम करने के लिए @DaRk -_- D0G का उत्तर संशोधित किया

/**
Arc Random for Double and Float
*/
public func arc4random <T: IntegerLiteralConvertible> (type: T.Type) -> T {
    var r: T = 0
    arc4random_buf(&r, sizeof(T))
    return r
}
public extension Int {
    /**
    Create a random num Int
    :param: lower number Int
    :param: upper number Int
    :return: random number Int
    By DaRkDOG
    */
    public static func random (lower: Int , upper: Int) -> Int {
        return lower + Int(arc4random_uniform(UInt32(upper - lower + 1)))
    }

}
public extension Double {
    /**
    Create a random num Double
    :param: lower number Double
    :param: upper number Double
    :return: random number Double
    By DaRkDOG
    */
    public static func random(lower: Double, upper: Double) -> Double {
        let r = Double(arc4random(UInt64)) / Double(UInt64.max)
        return (r * (upper - lower)) + lower
    }
}
public extension Float {
    /**
    Create a random num Float
    :param: lower number Float
    :param: upper number Float
    :return: random number Float
    By DaRkDOG
    */
    public static func random(lower: Float, upper: Float) -> Float {
        let r = Float(arc4random(UInt32)) / Float(UInt32.max)
        return (r * (upper - lower)) + lower
    }
}

सबसे तेज़ समाधान यहाँ! आपका बहुत बहुत धन्यवाद!
एंड्रयू


3

स्विफ्ट में ...

यह समावेशी है, कॉलिंग random(1,2)1 या 2 लौटाएगा, यह नकारात्मक संख्याओं के साथ भी काम करेगा।

    func random(min: Int, _ max: Int) -> Int {
        guard min < max else {return min}
        return Int(arc4random_uniform(UInt32(1 + max - min))) + min
    }

3

जवाब सिर्फ 1 लाइन कोड है:

let randomNumber = arc4random_uniform(8999) + 1000 //for 4 digit random number
let randomNumber = arc4random_uniform(899999999) + 100000000 //for 9 digit random number
let randomNumber = arc4random_uniform(89) + 10    //for 2 digit random number
let randomNumber = arc4random_uniform(899) + 100  //for 3 digit random number

वैकल्पिक समाधान है:

    func generateRandomNumber(numDigits: Int) -> Int{
    var place = 1
    var finalNumber = 0;
    var finanum = 0;
    for var i in 0 ..< numDigits {
        place *= 10
        let randomNumber = arc4random_uniform(10)         
        finalNumber += Int(randomNumber) * place
        finanum = finalNumber / 10
           i += 1
    }
    return finanum
}

हालांकि दोष यह है कि संख्या 0 से शुरू नहीं हो सकती है।


2

स्विफ्ट 4.2 के बाद से:

Int {    
    public static func random(in range: ClosedRange<Int>) -> Int
    public static func random(in range: Range<Int>) -> Int
}

जैसे इस्तेमाल किया:

Int.random(in: 2...10)

2

संपादित करें: स्विफ्ट 4.2+ अब यह प्रदान करता है:

(100...200).randomElement()

मेरा विस्तार करना मुहावरेदार है Range:

public extension Range where Bound == Int {
    var random: Int {
        return lowerBound + Int(arc4random_uniform(UInt32(upperBound - lowerBound)))
    }
}

public extension ClosedRange where Bound == Int {
    var random: Int {
        return lowerBound + Int(arc4random_uniform(UInt32(upperBound - lowerBound + 1)))
    }
}

उपयोग में:

let foo = (100..<600).random

शायद सिर्फ एक शैलीगत बात है। किसी भी विधि का कोई अंतर्निहित लाभ नहीं है, यह सिर्फ वही है जो आप के साथ अधिक सहज महसूस करते हैं।
ऐश

1
जो लोग इस "शैलीगत" पर विचार के लिए मैं उनके लिए एक भाषा सिफारिश की है: C। मज़े करो!
mxcl

मुझे यकीन है कि किसी ने 3 साल पहले किया था :) stackoverflow.com/questions/34712453/…
सिंह Dabus

1

मैंने निम्नलिखित कोड का उपयोग करके एक यादृच्छिक संख्या बनाने में सफलतापूर्वक पूरा किया:

var coin = arc4random_uniform(2) + 1

आशा है इससे आपको सहायता मिलेगी।


0

स्विफ्ट 3 एक्सकोड बीटा 5 सॉल्यूशन। टेड वैन गालन उत्तर पर आधारित।

extension Int
  {
     static func random(range: Range<Int> ) -> Int
    {
        var offset = 0

        if range.lowerBound < 0   // allow negative ranges
        {
            offset = Swift.abs(range.lowerBound)
        }

        let mini = UInt32(range.lowerBound + offset)
        let maxi = UInt32(range.upperBound   + offset)

        return Int(mini + arc4random_uniform(maxi - mini)) - offset
    }
}


0

आशा है कि यह काम कर रहा है। arc4random_uniform () के लिए सीमा के बीच यादृच्छिक संख्या बनाते हैं?

var randomNumber = Int(arc4random_uniform(6))
print(randomNumber)

0

संभवत: यह उपयोगी है कि स्विफ्ट 4 /Range एक्सकोड 9+ का उपयोग करके टेड वैन गालेन के उत्तर से विस्तार का यह थोड़ा अद्यतन संस्करण उपलब्ध हो :

extension CountableClosedRange where Bound == Int {
    var randomFromRange: Bound {
        get {
            var offset = 0
            if lowerBound < 0 {
                offset = abs(lowerBound)
            }
            let mini = UInt32(lowerBound + offset)
            let maxi = UInt32(upperBound + offset)
            return Int(mini + arc4random_uniform(maxi - mini)) - offset
        }
    }
}

let n = (-1000 ... 1000).randomFromRange
print(n)

या खुले और बंद अंतराल का समर्थन करने के लिए यह एक "हैकी" समाधान है:

extension CountableRange where Bound == Int {
    var randomFromRange: Bound {
        return uniformRandom(from: lowerBound, to: upperBound)
    }
}

extension CountableClosedRange where Bound == Int {
    var randomFromRange: Bound {
        return uniformRandom(from: lowerBound, to: upperBound - 1)
    }
}

func uniformRandom(from: Int, to: Int) -> Int {
    var offset = 0
    if from < 0 {
        offset = abs(from)
    }
    let mini = UInt32(from + offset)
    let maxi = UInt32(to + offset)
    return Int(mini + arc4random_uniform(maxi - mini)) - offset
}

सुनिश्चित नहीं है कि दोनों प्रकार के अंतरालों में एक साथ संपत्ति जोड़ने का कोई तरीका है।

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