0과 1 사이의 신속한 임의 부동


답변:


103

제수를 float로 초기화 해보십시오.

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

감사합니다. CGFloat로 분모를 캐스팅하려고했지만 작동하지 않았습니다. 그러나 먼저 float로 캐스팅 한 다음 CGFloat로 캐스팅하는 것처럼 보입니다.
Joe_Schmoe

2
필요가를 통해 갈 수 있습니다 Float- 다만 CGFloat(arc4random()) / CGFloat(UInt32.max).
Hamish

당신은 플로트 통과하지 않는 경우 @Joe_Schmoe는 / CGFloat는 부문은 큰 정수로 나눈 작은 정수이며, 항상 0을 반환합니다
탱 L

4
하지만 빠른 4.2 만 사용 : Float.random (에 : 0 .. <1)
앤드류 폴 시몬스

116

이것은 Int, Double, Float, CGFloat난수에 대한 확장입니다.

Swift 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 나는 수학을 이해하려고 노력하고 있습니다. Float 및 Double에 대해 random ()을 0xFFFFFFFF로 나누는 이유는 무엇입니까?
Crystal

2
스위프트에 대한 2 살펴 업데이트를 추가 @EthanMick)
YannSteph에게

1
"cannot call value of non-function type 'CGFloat'"오류가 CGFloat.random (min : 0.1, max : 10.1)을 사용하려고 할 때 나타납니다
Andrew

1
Swift 4에는 업데이트가 필요하지 않습니다.
RyuX51

1
@YannickSteph Swift 5 및 Xcode 10.2에서 줄은 return Float(arc4random()) / 0xFFFFFFFF이제 경고를 제공합니다 '4294967295' is not exactly representable as 'Float'; it becomes '4294967296'.. 그 경고를 해결하는 방법을 아십니까? Float(UInt32.max)대신 나누려고합니다 .
peacetype


26

Swift 3에 대한 Sandy Chapman의 답변 업데이트 :

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().

편집 나는 오늘 (Swift 4) 다음과 같이 쓸 것이라고 생각합니다.

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

참고 Swift 4.2는 기본 난수 생성을 도입하며이 모든 것이 문제가됩니다.


16

여기 프레임 워크는 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
    }
}

.NET 용으로 컴파일 할 때는 작동하지 않습니다 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
    }
}

Ints는 IntervalType. Range대신 사용 합니다. CollectionType유형에 대해이 작업을 수행하는 이점은 자동으로 DictionaryArray유형 으로 전달된다는 것 입니다.

예 :

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

우리가 IntervalType 확장하는 경우 우리가 아닌 원래의 질문뿐만 아니라 INTS에 대한 작업이를 얻을 수 있지만, 가능성이 다음 단계를 보인다 어떻게
Joe_Schmoe

1
@Joe_Schmoe : 나는 사용에 대한 자세한 내용은 내 대답을 업데이 트했습니다 .random()Int, S DictionaryS와 Array이야
샌디 채프먼

난 정말이 솔루션처럼,하지만 난 더 일반적인 관행 포함 통해 업데이트
tbondwilkinson

1
Swift 3에서 중단됨
matt

7

스위프트 5

let randomFloat = CGFloat.random(in: 0...1)

6

jmduke가 제안한 것은 기능이 약간 변경된 상태로 Playground에서 작동하는 것 같습니다.

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

[더블]이 필요한 경우. 0과 1 사이입니다. 그게 다입니다.


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, Swift 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))
}

결과

여기에 이미지 설명 입력

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