Swift Probability of Random Number Being Selected

Swift probability of random number being selected?

Why not use the Swift switch statement combined with pattern matching:

// create a random percent, with a precision of one decimal place
func randomPercent() -> Double {
return Double(arc4random() % 1000) / 10.0;
}

let randomNumber = randomPercent()
switch(randomNumber) {
case 0..<55:
println("10% worse - 35% better then current item level")
case 55..<90:
println("36% better to 90% better then current item level")
case 90..<95:
println("91% better to 200% better then current item level")
case 95..<97.5:
println("201% better to 500% better then current item level")
default:
println("500% better to 2000% better then current item level")
}

This makes the logic very clear.

Generate random numbers with a given distribution

This is a Swift implementation strongly influenced by the various
answers to Generate random numbers with a given (numerical) distribution.

For Swift 4.2/Xcode 10 and later (explanations inline):

func randomNumber(probabilities: [Double]) -> Int {

// Sum of all probabilities (so that we don't have to require that the sum is 1.0):
let sum = probabilities.reduce(0, +)
// Random number in the range 0.0 <= rnd < sum :
let rnd = Double.random(in: 0.0 ..< sum)
// Find the first interval of accumulated probabilities into which `rnd` falls:
var accum = 0.0
for (i, p) in probabilities.enumerated() {
accum += p
if rnd < accum {
return i
}
}
// This point might be reached due to floating point inaccuracies:
return (probabilities.count - 1)
}

Examples:

let x = randomNumber(probabilities: [0.2, 0.3, 0.5])

returns 0 with probability 0.2, 1 with probability 0.3,
and 2 with probability 0.5.

let x = randomNumber(probabilities: [1.0, 2.0])

return 0 with probability 1/3 and 1 with probability 2/3.


For Swift 3/Xcode 8:

func randomNumber(probabilities: [Double]) -> Int {

// Sum of all probabilities (so that we don't have to require that the sum is 1.0):
let sum = probabilities.reduce(0, +)
// Random number in the range 0.0 <= rnd < sum :
let rnd = sum * Double(arc4random_uniform(UInt32.max)) / Double(UInt32.max)
// Find the first interval of accumulated probabilities into which `rnd` falls:
var accum = 0.0
for (i, p) in probabilities.enumerated() {
accum += p
if rnd < accum {
return i
}
}
// This point might be reached due to floating point inaccuracies:
return (probabilities.count - 1)
}

For Swift 2/Xcode 7:

func randomNumber(probabilities probabilities: [Double]) -> Int {

// Sum of all probabilities (so that we don't have to require that the sum is 1.0):
let sum = probabilities.reduce(0, combine: +)
// Random number in the range 0.0 <= rnd < sum :
let rnd = sum * Double(arc4random_uniform(UInt32.max)) / Double(UInt32.max)
// Find the first interval of accumulated probabilities into which `rnd` falls:
var accum = 0.0
for (i, p) in probabilities.enumerate() {
accum += p
if rnd < accum {
return i
}
}
// This point might be reached due to floating point inaccuracies:
return (probabilities.count - 1)
}

Increase random number probability swift

For a given max damage probability of pMaxDamage (say, pMaxDamage = 0.80), one simple solution is to generate a random number, say r, in [0,1] and output:

  • maxDamage if r <= pMaxDamage,
  • a random damage in range [minDamage, maxDamage], otherwise.

E.g.:

class Hero {
let heroName: String
let pMaxDamage: Double // probability to generate max damage

init(heroName: String, pMaxDamage: Double) {
self.heroName = heroName
self.pMaxDamage = pMaxDamage
}

func generateDamage(minDamage minDamage: Double, maxDamage: Double) -> Double {
let r = (Double(arc4random()) / 0xFFFFFFFF)

return r <= pMaxDamage ? maxDamage
: round(100*((r-pMaxDamage)/(1-pMaxDamage)*(minDamage-maxDamage)+maxDamage))/100
}
}

For the above implementation the r-damage (r uniform random number in [0, 1]) response curve looks as follows:

Sample Image

Example usage:

let myHero = Hero(heroName: "Foo", pMaxDamage: 0.80)
for _ in (1...10) {
print("Slash! <\(myHero.generateDamage(minDamage: 5, maxDamage: 15)) damage>")
}

Example output:

Slash! <15.0 damage>
Slash! <12.68 damage>
Slash! <15.0 damage>
Slash! <15.0 damage>
Slash! <5.72 damage>
Slash! <15.0 damage>
Slash! <15.0 damage>
Slash! <15.0 damage>
Slash! <15.0 damage>
Slash! <15.0 damage>

If you want your damage values to only take integer values, an alternative solution would be roulette wheel selection with

  • pMaxDamage probability of picking maxDamage,
  • uniform (1-pMaxDamage)/(numDamagePoints-1) probability of picking any of the remaining {minDamage, minDamage+1, ..., maxDamage-1} damage values.

How to increase or decrease the probability of an item of an array being picked

more of a mathematical question than an UI question, but nevertheless:

let probs = [
1 : 10,
2 : 20,
3 : 30,
4 : 35,
5 : 5
]

func randomWithProbability(distribution: [Int : Int]) -> Int {

var distributionArray: [Int] = []
distribution.forEach { (key: Int, value: Int) in
let new = Array(repeating: key, count: value)
distributionArray.append(contentsOf: new)
}
let r = Int.random(in: 0..<distributionArray.count)
return distributionArray[r]

}

and to prove it:

struct ContentView: View {

private var results: [Int]

init() {
results = [0,0,0,0,0]
for _ in 0..<1000 {
let i = randomWithProbability(distribution: probs)
results[i-1] += 1
}
}

var body: some View {

VStack(alignment: .leading) {
ForEach(results.indices) { i in
HStack {
Text("\(i)")
Color.blue
.frame(width: CGFloat(results[i]), height: 40)
}
}
}
}
}

Sample Image

How to generate a random number in Swift?

Swift 4.2+

Swift 4.2 shipped with Xcode 10 introduces new easy-to-use random functions for many data types.
You can call the random() method on numeric types.

let randomInt = Int.random(in: 0..<6)
let randomDouble = Double.random(in: 2.71828...3.14159)
let randomBool = Bool.random()

Swift - A function to work out probability given defined percentages

The answer is, buy an infinite number of packs. As the number of packs of cards goes up, the probability of getting at least 1 Charizard goes up, by very small increments, but it is never certain. (as the number of packs you purchase approaches infinity, your probability of getting at least 1 Charizard asymptotically approaches 1, or 100%.)

I belive you figure it like this:

A probability of getting a card is 1.1% That means the probability of NOT getting that card is 100-1.1, or 98.9% (or 0.989)

Each time you get a pack, your probability of NOT getting a Charizard should be

0.989number_of_packs

(0.989 raised to the number_of_packs_purchased power)

After 10 packs, your probability of NOT getting a Charizard would be 0.98910, or ≈0.895 (89.5%, which means your chance of GETTING a Charizard wold be 100%-89.5% = 10.5%)

After purchasing 100 packs, your probability of not getting a Charizard would be 0.989100, or about 0.33, or about a 66% chance of getting a Charizard



Related Topics



Leave a reply



Submit