arc4random_uniform ()의 범위 사이에서 임의의 숫자를 만드는 방법은 무엇입니까?


129

이 코드 비트의 목표는 무작위로 두 개의 주사위를 굴리는 것입니다. 우리 모두 알고 있듯이 일반 주사위에는 6면 만 있으므로 arc4random_uniform (UInt32)에 액세스하기 위해 Foundation을 가져 왔습니다. 나는 무작위로 0을 얻는 것을 피하기 위해 (1..7) 범위를 사용하려고 시도했지만 너무 좋아하지 않는 오류를 반환했습니다. 나는 이것을 시도했다 :

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

그러나 그 반환

제공된 인수를 허용하는 'init'에 대한 과부하를 찾을 수 없습니다.

나는 이것이 당신을 도울 수있는 놀라운 뎁을위한 충분한 정보가되기를 바랍니다 :)

나는 운동장에서 신속하게 연습하기 위해 이것을하고 있습니다. 이 작업을 수행하는 방법을 반드시 배우는 것은 아닙니다. 실제 앱을 빌드하기 전에 땜질하고 있습니다. : D

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

'Range $ 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) + 11-6의 범위를 갖기 위해 해야한다고 생각합니다 . 나는 iOS 목표 C를하지 않으며 신속한 언어에 대한 지식이 없습니다. 임의의 방법은 0-5를 반환하고 + 1은
Sky

1
Range는 객체 데이터 자체이며, 정수 데이터가 아니기 때문에 인수가 (UInt32)u_int32_t arc4random_uniform(u_int32_t upper_bound);
Sky

아하! 하늘 감사합니다! 그것이 0보다 적어지면 테스트하기 위해 어설 션을 수행했으며 이것이 내가 그것을 확인할 수 있도록 정확히 내가 대답으로 넣은 것임을 확인할 수 있습니다!
arcreigh,

확률 = Int (arc4random_uniform (UInt32 (total))) – 비특이적 인 캐스팅 불만이 여러 개인 경우 (typeahead / 헤더가 작동하지 않기 때문에)
bshirley

답변:


260

당신이해야한다고 믿습니다

dice1 = arc4random_uniform(6) + 1;

나는 범위 1-6을 얻는다. 나는 iOS 목표 C를하지 않으며 신속한 언어에 대한 지식이 없다. random 메소드는 0과 5 사이의 값을 반환해야하며 + 1은 1과 6 사이의 값을 만듭니다.

10-30 사이의 범위가 필요하다면 그냥하십시오.

int random = arc4random_uniform(21) + 10;

2
@JoeSmith 당신이 이것에 정확히 맞다면, 상한을 포함하지 않기 때문에 10-30 사이의 범위를 반환하려면 arc4random_uniform (21) +10이어야합니다. "arc4random_uniform (20) +10"부분은 커뮤니티 편집 및 투표를 기반으로합니다.
하늘

예, 방금 테스트를 거쳐 임의의 색상을 얻습니다 (예 : 0-255 사이의 임의의 값을 원함). "arc4random_uniform (256) + 0"
Chris Allinson

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 Swift의 진정한 사용법!
Kalzem

나는 범위 확장을 좋아한다.
David James

좋은 대답입니다. 내 유일한 경고는 randomInt :가 Int 또는 Range의 자연스러운 확장이 아니라고 말하는 것입니다. 유틸리티 파일에서 이것을 독립형 기능으로 추가하기 만하면됩니다.
빈스 오 설리번

요구는, 빠른 3 업데이트 될 range.lowerBound와 range.startIndex을 대신 교체 및 endIndex 지금 UPPERBOUND되는
조셉 Astrahan

62

꽤 좋은 답변이 있지만 양수에 대해 개인적으로 선호하는 Swift 난수 생성 기능을 공유하고 싶었습니다.

스위프트 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

다음은 Swift 3에 대한 빠른 업데이트이며 보너스로 SignedInteger 프로토콜을 준수하는 모든 값 유형에서 작동합니다 .Int16, Int32 등을 지정해야하는 핵심 데이터 응용 프로그램에 훨씬 편리합니다. 정말 다음 교체 전체 기능을 복사뿐만 아니라 부호없는 정수에 대한 작업을 필요 SignedIntegerUnsignedInteger하고 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

Swift 4에서 toIntMax ()가 제거되었으므로 이제 공통 정수 유형으로 변환하는 다른 방법을 사용해야합니다. 이 예에서는 필자의 목적에 맞게 충분히 큰 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
나는 이것을 보았고 (max-min) = 5이기 때문에 잘못되어야한다고 생각했다 .0에서 4 사이의 임의의 정수를 산출했다. 그러나 코드를 Xcode 놀이터에 넣으면 작동한다는 것이 분명했습니다. endIndex가 "컬렉션의 첫 번째 '종료'위치"를 반환하기 때문에 max가 실제로 7과 같은 이유입니다. (Apple 설명서에 명시된대로). 그래서 좋은 대답과 유용한 학습 연습이 있습니다.
빈스 오 설리번

이것은 음의 정수에서도 작동합니다. randomNumber(-3 ... -1)앞뒤에 공백이있는 한 작동합니다 .... random(-3 ..< -1마지막 숫자도 제외하는 데 사용할 수 있습니다.
카터 메 드린

정수가 아닌 사람과 함께이 작업을 하려면 ClosedInterval대신에 사용하십시오 Range.
카터 메 드린

나는하지 않을 것입니다. 간격 유형은 Swift 3에서 더 이상 사용되지 않습니다. Generics를 사용하여 코드의 기능을 확장 할 수있는 방법이있을 수 있지만 조사 할 시간, 성향 또는 이유는 없었습니다.
Ash

1
코드의 일반화 된 정수 버전이 있습니다.
Ash


18

원하는 경우 난수 에 대해 생성하십시오 . 이것은 숫자 Int와 Double, Float의 확장입니다.

/**
    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)

이항 연산자 / 두 개의 더블 피연산자에 적용 할 수 없음
Jason G

13

스위프트 3/4 :

func randomNumber(range: ClosedRange<Int> = 1...6) -> Int {
    let min = range.lowerBound
    let max = range.upperBound
    return Int(arc4random_uniform(UInt32(1 + max - min))) + min
}

8

arc4random_uniform ()이 다음과 같이 정의 되었기 때문입니다.

func arc4random_uniform(_: UInt32) -> UInt32

UInt32를 입력으로 사용하고 UInt32를 뱉어냅니다. 값의 범위를 전달하려고합니다. arc4random_uniform은 0과 0 사이의 난수를 제공하므로 (독점적으로), 예를 들어 [-50, 50]사용할 수있는 것처럼 -50과 50 사이의 난수를 찾고 싶었습니다.arc4random_uniform(101) - 50


Sky는 내 질문에 완벽하게 대답했습니다. 동일한 말을하고 있다고 생각합니다 .dice1,2 = arc4random_uniform (6) +1을 설정하여 실제로 범위를 1-6으로 설정했는지 확인하십시오. 어설 션으로 테스트했습니다. D
arcreigh

6

Swift 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

답은 한 줄의 코드입니다.

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

편집 : Swift 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

아마 문체 일 것입니다. 두 방법 모두에 고유 한 이점이 없으며 더 편하게 느끼는 것입니다.
Ash

1
이 "스타일"을 고려하는 사람들에게는 다음과 같은 언어 권장 사항이 있습니다 C. 즐기세요!
mxcl

나는 확실히 누군가가 이미 2 년 전을 수행했다입니다 :) stackoverflow.com/questions/34712453/...
레오 버스들이시길

1

다음 코드를 사용하여 난수를 성공적으로 생성했습니다.

var coin = arc4random_uniform(2) + 1

이것이 당신을 도울 수 있기를 바랍니다.


0

스위프트 3 Xcode 베타 5 솔루션. Ted van Gaalen Answer를 기반으로합니다.

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

var rangeFromLimits = arc4random_uniform ((UPPerBound-LOWerBound) + 1)) + LOWerBound;


0

이것이 효과가 있기를 바랍니다. arc4random_uniform ()의 범위 사이에서 임의의 숫자를 만드시겠습니까?

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

0

아마도 Swift 4 / Xcode 9+를Range 사용하는 Ted van Gaalen의 답변에서 약간 업데이트 된 확장 버전이 유용하다는 것을 알 수 있습니다 .

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
}

두 유형의 간격에 동시에 속성을 추가하는 방법이 있는지 확실하지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.