Reputation: 33
I am trying to shuffle an array of numbers and then store the resulting random array in a variable. But I want the resulting random array to have elements which always sum up to 1.
var numbers = [1,0.5,0.25,0.125,0.0625]
var newTime = [Double]()
var x = numbers.shuffled()
for _ in 0..<x.count {
newTime.append(x.random_element())
}
var sum = newTime.reduce(0, +)
for _ in 0..<newTime.count {
if sum == 1 {
print("Final Sum: \(newTime)")
}
if sum > 1 {
let rand = Int(arc4random_uniform(UInt32(newTime.count)))
newTime.remove(at: rand)
} else if sum < 1 {
newTime.append(x.random_element())
}
}
EDITED: (following Duncan's suggestion)
var numbers = [1,0.5,0.25,0.125,0.0625]
var newTime = [Double]()
var x = numbers.shuffled()
for _ in 0..<x.count {
newTime.append(x.random_element())
}
var sum = newTime.reduce(0, +)
newTime.append(1.0 - sum)
print(newTime)
This works so long as (1.0-sum) is a positive number. In this case a positive number is appended to the array making the sum total of all the elements in the array =1.0. However, if (1.0-sum) is a negative number then it does not work for me because the resulting newTime array will have all the previous elements in that array plus one more negative number which basically sums up to 1.0. In this case the resulting newTime = [0.125, 0.25, 0.0625, 1.0, 1.0, -1.4375]. Whereas I am expecting newTime = [1.0] as sum of rest of the elements is 1.4375, therefore, I need them to be removed from the newTime array.
Hope I am able to explain things clearly.
Upvotes: 0
Views: 141
Reputation: 131471
Your goal is confused, and your code doesn't make much sense. You say you want to shuffle an array, but then you say you want the sum of the elements in the array to always add up to 1. The order of the elements in an array has no effect on the sum. It sounds like you want to create a random array of floating point values who's sum is 1.0, and then you want to randomize it.
Those are 2 different things.
If you're using Swift 4.2 you could create an array of objects where the sum is 1.0 like this:
var array = [Double]()
//create an array of values ranging from -2.0 to 2.0
for _ in 1...10 {
array.append(Double(Int.random(in: -2000...2000))/1000.0)
}
let sum = array.reduce(0, +)
//Add one more value that brings the sum of the array contents to ≈ 1.0
array.append(1.0 - sum)
Then to shuffle the array just use
array.shuffle()
Due to the limitations of floating point, the sum of the array may not be exactly 1. You might get values like 0.99999999998 or 1.0000000004, but if you round the sum to 3 decimal places it will be 1.000
.
Upvotes: 1