How to Increment Exponentially in Swift

Exponentiation operator in Swift

There isn't an operator but you can use the pow function like this:

return pow(num, power)

If you want to, you could also make an operator call the pow function like this:

infix operator ** { associativity left precedence 170 }

func ** (num: Double, power: Double) -> Double{
return pow(num, power)
}

2.0**2.0 //4.0

Increment value increasing exponentially

Ah silly mistake. I was calling this through another agent whose population was increasing per frame!

How to make UISlider output nice rounded numbers exponentially?

The easiest answer is to use a Segmented Control with the different 'step sizes'. Depending on what option the user selects, is what step size your slider will have. I'd even recommend that this is perhaps a more user friendly way to approach it :).

Feel free to use Dapp to play with the look of your app and see how a segmented control might fit with the design.

However... you wanted a leaner approach ;).

I started writing the 10 or so steps needed, but I stopped when I realised you had probably already come to a similar solution. Your string array idea is fine, I assume you will simply convert the slider value to an integer and grab the relevant index from the array?

Sometimes as programmers we go too far with our approaches to a problem. Yes, a string array isn't the most 'flexible' solution but it is fast! And, I'd argue that even a genius mathematical solution isn't as flexible as you may think. Also, if you don't plan on changing the values anytime soon and don't need different slider ranges on different sliders, then it makes sense to just create a static array.

Good luck! :)

Express for loops in swift with dynamic range

Using a helper function (originally defined at Converting a C-style for loop that uses division for the step to Swift 3)

public func sequence<T>(first: T, while condition: @escaping (T)-> Bool, next: @escaping (T) -> T) -> UnfoldSequence<T, T> {
let nextState = { (state: inout T) -> T? in
// Return `nil` if condition is no longer satisfied:
guard condition(state) else { return nil }
// Update current value _after_ returning from this call:
defer { state = next(state) }
// Return current value:
return state
}
return sequence(state: first, next: nextState)
}

you can write the loop as

let num = 1000
for i in sequence(first: 5, while: { num/$0 > 0 }, next: { $0 * 5 }) {
print(i)
}

A simpler solution would be a while-loop:

var i = 5
while num/i > 0 {
print(i)
i *= 5
}

but the advantage of the first solution is that the scope of the loop variable is limited to the loop body, and that the loop variable is a constant.

Swift 3.1 will provide a prefix(while:) method for sequences,
and then the helper function is no longer necessary:

let num = 1000
for i in sequence(first: 5, next: { $0 * 5 }).prefix(while: { num/$0 > 0 }) {
print(i)
}

All of above solutions are "equivalent" to the given C loop.
However, they all can crash if num is close to Int.max
and $0 * 5 overflows. If that is an issue then you have to check
if $0 * 5 fits in the integer range before doing the multiplication.

Actually that makes the loop simpler – at least if we assume that
num >= 5 so that the loop is executed at least once:

for i in sequence(first: 5, next: { $0 <= num/5  ? $0 * 5 : nil }) {
print(i)
}

Swift running sum

The general combinator you're looking for is often called scan, and can be defined (like all higher-order functions on lists) in terms of reduce:

extension Array {
func scan<T>(initial: T, _ f: (T, Element) -> T) -> [T] {
return self.reduce([initial], combine: { (listSoFar: [T], next: Element) -> [T] in
// because we seeded it with a non-empty
// list, it's easy to prove inductively
// that this unwrapping can't fail
let lastElement = listSoFar.last!
return listSoFar + [f(lastElement, next)]
})
}
}

(But I would suggest that that's not a very good implementation.)

This is a very useful general function, and it's a shame that it's not included in the standard library.

You can then generate your cumulative sum by specializing the starting value and operation:

let cumSum = els.scan(0, +)

And you can omit the zero-length case rather simply:

let cumSumTail = els.scan(0, +).dropFirst()


Related Topics



Leave a reply



Submit