0

I am trying calculate 2^64 with my custom-pow function.

So far I built 2 versions of it. Version 2 works.

I think version 1 should also work, but Swift crashes with an overflow error. I think It must work because I am "not" loading a higher number than I'm allowed! Why it is happening?

Version 1.0.0

func powV1(number: Int8, power: Int8) -> UInt64 {
    var returnValue: UInt64 = 1
    
    for _ in 1 ... power {
        returnValue = returnValue * UInt64(number)
    }
    
    return returnValue
}

Version 2.0.0

func powV2(number: Int8, power: Int8) -> Decimal {
    var returnValue: Decimal = 1
    
    for _ in 1 ... power {
        returnValue = returnValue * Decimal(number)
    }
    
    return returnValue
}

And here is call site:

powV1(number: 2, power: 64) // ← Error: OverFlow

PS: Everyone is very welcome to improve version 2.0.0

Update:

    func powV1_0_1(number: Int8, power: Int8) -> UInt64 {
    var returnValue: UInt64 = 1
    
    for i in 1 ... power {
        
        if i == power && power == 64
        {
            let last = Decimal(returnValue)*Decimal(number) - 1
            returnValue = UInt64(last)  // Error: Decimal should conform BinaryInteger says Error!?!
        }
        else
        {
            returnValue = returnValue*UInt64(number)
        }
    }
    
    return returnValue
}
ios coder
  • 1
  • 4
  • 31
  • 91
  • What's with all the ! and the ? – Alexander Nov 17 '20 at 17:37
  • FYI: You should use the proper terminology. In the sample `10^9`, `10` is called the **base**, `9` is the **exponent**, and the whole expression `10^9` is called the **power**. So a better naming of this function might be `power(base: 2, exponent: 64)`. Though I would use an extension to achieve a more english-like syntax: `2.raisedToThePower(of: 64)` – Alexander Nov 17 '20 at 17:47
  • Very good advice! any other better coding for faster run? – ios coder Nov 17 '20 at 18:02
  • 3
    Yeah: don't write your own `pow`, use the built-in one that uses dedicate CPU hardware instead of looping multiplications in software – Alexander Nov 17 '20 at 18:15
  • https://stackoverflow.com/q/26794282/2303865 – Leo Dabus Nov 17 '20 at 18:35
  • You are welcome. – Leo Dabus Nov 17 '20 at 18:45
  • 1
    @Omid See https://stackoverflow.com/a/40824893/3141234 You can lookup the implementation of `__ieee754_pow`, but it's remarkably complicated, and uses all kind of clever bit manipulation tricks – Alexander Nov 17 '20 at 19:09

1 Answers1

3

The problem is that the max value UInt64 can hold is 2^64-1, not 2^64, so 2^64 rightly overflows a UInt64.

Moreover, your function takes signed integers, whose powers can result in negative numbers, so returning a UInt64 is a bad idea. Or if you really want a UInt64, you should ensure the inputs can't produce a negative output (if number is negative, power should be an even number).

Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
  • @Omid you can convert a `Decimal` to a `UInt64` using `NSDecimalNumber(decimal: yourDecimal).uint64Value`, however, what are you actually trying to achieve? Are you doing this as an exercise to learn Swift/algorithms? In pretty much any other case, don't reinvent the wheel. Use the built-in, tested and optimised implementation. – Dávid Pásztor Nov 17 '20 at 18:03