如何从Swift 4中的正态分布返回float或double?

时间:2018-03-24 21:56:41

标签: swift4 normal-distribution

我试图在正常分布中返回一个浮点数或一个双精度值,其中在Swift4中,均值= 0,标准偏差= 4。我能得到的最接近的是使用GameplayKit - > GKGaussianDistribution在以下代码中实现:

func generateForecast() {
    let gauss = GKGaussianDistribution(randomSource: self.source, mean: 0.0, deviation: 4.0)
    self.epsilon = gauss.nextInt()
}

我的问题是我打电话

gauss.nextInt()

我显然得到一个整数。当我尝试

gauss.nextUniform()

我得到介于-1和1之间的数字。

是否有一种相当简单的方法可以从Swift4中的正态分布返回float或double,而不是在-1和1之间的Int或float?

import AppKit
import PlaygroundSupport
import GameplayKit

let nibFile = NSNib.Name(rawValue:"MyView")
var topLevelObjects : NSArray?

Bundle.main.loadNibNamed(nibFile, owner:nil, topLevelObjects: &topLevelObjects)
let views = (topLevelObjects as! Array<Any>).filter { $0 is NSView }

// Present the view in Playground
PlaygroundPage.current.liveView = views[0] as! NSView

let s = 0.001
var auto_corr: [Int] = []

class Market {
    var numAgents: Int
    var traders: [Agent] = []
    var price: Double
    var epsilon: Int
    var priceHist: [Double] = []
    var returnHist: [Double] = []
    var returnRealHist: [Double] = []
    var logReturn: Double = 0
    var realReturn: Double = 0
    let source = GKRandomSource()

    init(numAgents: Int, price: Double, epsilon: Int) {
        self.numAgents = numAgents
        self.price = price
        self.epsilon = epsilon
        for _ in 1...numAgents {
            self.traders.append(Agent(phi: 1, theta: 1))
        }
    }

    func generateForecast() {
        let gauss = GKGaussianDistribution(randomSource: self.source, mean: 0.0, deviation: 4.0)
        self.epsilon = gauss.nextInt()
    }

}

1 个答案:

答案 0 :(得分:1)

GKGaussianDistribution的文档没有提及它会覆盖基类的nextUniform(),所以不要假设它会为您返回正常分布的值:

您可以使用Box-Muller Transformation

滚动自己的高斯分布
class MyGaussianDistribution {
    private let randomSource: GKRandomSource
    let mean: Float
    let deviation: Float

    init(randomSource: GKRandomSource, mean: Float, deviation: Float) {
        precondition(deviation >= 0)
        self.randomSource = randomSource
        self.mean = mean
        self.deviation = deviation
    }

    func nextFloat() -> Float {
        guard deviation > 0 else { return mean }

        let x1 = randomSource.nextUniform() // a random number between 0 and 1
        let x2 = randomSource.nextUniform() // a random number between 0 and 1
        let z1 = sqrt(-2 * log(x1)) * cos(2 * Float.pi * x2) // z1 is normally distributed

        // Convert z1 from the Standard Normal Distribution to our Normal Distribution
        return z1 * deviation + mean 
    }
}

我故意没有从GKRandomDistribution继承它,因为我需要覆盖其他方法但与此问题无关。