我怎样才能 return 从 Swift 4 中的正态分布得到一个浮点数或双精度数?

How can I return a float or double from normal distribution in Swift 4?

我正在尝试 return 从 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 之间的数字。

有没有一种相当简单的方法来 return 来自 Swift4 中正态分布的浮点数或双精度数而不是 Int 或介于 -1 和 1 之间的浮点数?

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 { [=15=] 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()
    }

}

GKGaussianDistribution 的文档没有提到它从基数 class 覆盖 nextUniform(),所以不要假设它会为您 return 正态分布值:

您可以使用 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 中继承 class 因为还有其他方法我需要覆盖但与这个问题无关。