Integer 如何在Swift语言中获得某个整数的幂?

Integer 如何在Swift语言中获得某个整数的幂?,integer,double,swift,pow,Integer,Double,Swift,Pow,我最近在学习swift,但我有一个基本问题,找不到答案 我想买点像这样的东西 var a:Int = 3 var b:Int = 3 println( pow(a,b) ) // 27 但是pow函数只能处理double number,不能处理integer,我甚至不能用double(a)或a.double()之类的方法将int转换为double 为什么它不提供整数的幂?它肯定会返回一个没有歧义的整数! 为什么我不能将整数转换为双精度?它只是将3改为3.0(或3.00000…随便什么) 如果

我最近在学习swift,但我有一个基本问题,找不到答案

我想买点像这样的东西

var a:Int = 3
var b:Int = 3 
println( pow(a,b) ) // 27
但是pow函数只能处理double number,不能处理integer,我甚至不能用double(a)或a.double()之类的方法将int转换为double

为什么它不提供整数的幂?它肯定会返回一个没有歧义的整数! 为什么我不能将整数转换为双精度?它只是将3改为3.0(或3.00000…随便什么)

如果我得到两个整数,我想做幂运算,我怎么能顺利地做呢


谢谢

除了变量声明有语法错误之外,这正是您所期望的。您所要做的就是将
a
b
转换为双倍并将值传递给
pow
。然后,如果您使用2个Int,并且希望在操作的另一端返回一个Int,那么只需返回Int即可

import Darwin 

let a: Int = 3
let b: Int = 3

let x: Int = Int(pow(Double(a),Double(b)))

如果您真的想要一个“仅限Int”的实现,并且不想强制执行Double,那么您需要实现它。这里是一个微不足道的实现;有更快的算法,但这会起作用:

func pow (_ base:Int, _ power:UInt) -> Int {
  var answer : Int = 1
  for _ in 0..<power { answer *= base }
  return answer
}

> pow (2, 4)
$R3: Int = 16
> pow (2, 8)
$R4: Int = 256
> pow (3,3)
$R5: Int = 27
func-pow(uu-base:Int,uu-power:UInt)->Int{
答案:Int=1
对于uu0..pow(2,4)
$R3:Int=16
>战俘(2,8)
$R4:Int=256
>战俘(3,3)
$R5:Int=27

在实际的实现中,您可能需要一些错误检查。

如果您愿意,您可以声明一个
中缀
操作符来执行此操作

// Put this at file level anywhere in your project
infix operator ^^ { associativity left precedence 160 }
func ^^ (radix: Int, power: Int) -> Int {
    return Int(pow(Double(radix), Double(power)))
}

// ...
// Then you can do this...
let i = 2 ^^ 3
// ... or
println("2³ = \(2 ^^ 3)") // Prints 2³ = 8
我使用了两个插入符号,所以您仍然可以使用

Swift 3的更新

在Swift 3中,“幻数”
优先级
优先级组取代

precedencegroup PowerPrecedence { higherThan: MultiplicationPrecedence }
infix operator ^^ : PowerPrecedence
func ^^ (radix: Int, power: Int) -> Int {
    return Int(pow(Double(radix), Double(power)))
}

// ...
// Then you can do this...
let i2 = 2 ^^ 3
// ... or
print("2³ = \(2 ^^ 3)") // Prints 2³ = 8
例如:

calc (2,2)
CustomMath.pow(1,1)
我更喜欢这个

func ^ (left:NSNumber, right: NSNumber) -> NSNumber {
    return pow(left.doubleValue,right.doubleValue)
}
var a:NSNumber = 3
var b:NSNumber = 3 
println( a^b ) // 27
再详细一点

   infix operator ^^ { associativity left precedence 160 }
   func ^^ (radix: Int, power: Int) -> Int {
       return Int(pow(CGFloat(radix), CGFloat(power)))
   }
或者只是:

var a:Int = 3
var b:Int = 3
println(pow(Double(a),Double(b)))

如果您不喜欢运算符重载(尽管阅读您的代码的人可能很清楚
^
解决方案),您可以快速执行:

let pwrInt:(Int,Int)->Int = { a,b in return Int(pow(Double(a),Double(b))) }
pwrInt(3,4) // 81

将答案组合成一组重载函数(并使用“**”而不是其他一些语言使用的“^^^”),这对我来说更清楚:

使用Float时,可能会失去精度。如果使用数字文字以及整数和非整数的混合,默认情况下将使用Double。出于风格/可读性的原因,我个人喜欢使用数学表达式而不是像pow(a,b)这样的函数,但这只是我自己

任何会导致pow()抛出错误的运算符也会导致这些函数抛出错误,因此错误检查的负担仍然在于使用幂函数的代码。KISS,IMHO

使用本机pow()函数可以例如取平方根(2**0.5)或求逆(2**-3=1/8)。由于可以使用逆或分数指数,我编写了所有代码来返回pow()函数的默认双精度类型,它应该返回最精确的值(如果我正确地记得文档的话)。如果需要,可以将其类型转换为Int或Float或其他类型,可能会损失精度

2 ** -3  = 0.125
2 ** 0.5 = 1.4142135623731
2 ** 3   = 8

尝试组合重载时,我尝试使用泛型,但无法使其工作。我最终决定使用NSNumber,而不是尝试重载或使用泛型。这简化为以下内容:

typealias Dbl = Double // Shorter form
infix operator ** {associativity left precedence 160}
func ** (lhs: NSNumber, rhs: NSNumber) -> Dbl {return pow(Dbl(lhs), Dbl(rhs))}
下面的代码与上面的函数相同,但实现了错误检查,以查看参数是否可以成功转换为双精度

func ** (lhs: NSNumber, rhs: NSNumber) -> Dbl {
    // Added (probably unnecessary) check that the numbers converted to Doubles
    if (Dbl(lhs) ?? Dbl.NaN) != Dbl.NaN && (Dbl(rhs) ?? Dbl.NaN) != Dbl.NaN {
        return pow(Dbl(lhs), Dbl(rhs))
    } else {
        return Double.NaN
    }
}

有时,将
Int
转换为
Double
不是一个可行的解决方案。在某些程度上,这种转换会降低精度。例如,以下代码不会返回您可能直观期望的结果

Double(Int.max - 1) < Double(Int.max) // false!
Double(Int.max-1)
如果您需要高量级的精度,并且不需要担心负指数——这通常不能用整数来解决——那么此实现是您的最佳选择。根据“在非对称加密技术中,对大数进行模幂运算的标准方法。”

//使用Swift 5.0
func-pow(uu-base:T,uu-power:T)->T{
func expBySq(y:T,x:T,n:T)->T{
前提条件(n>=0)
如果n==0{
返回y
}如果n==1,则为else{
返回y*x
}如果n是多个(of:2),则为else{
返回expBySq(y,x*x,n/2)
}否则{//n是奇数
返回expBySq(y*x,x*x,(n-1)/2)
}
}
返回expBySq(1,基本,电源)
}

注意:在本例中,我使用了一个通用的
T:BinaryInteger
。因此,您可以使用
Int
UInt
或任何其他类似整数的类型。

mklbtz通过平方运算作为计算整数幂的标准算法来进行幂运算,这是正确的,但该算法的尾部递归实现似乎是一个错误有点混乱。请参阅,了解C中通过平方运算实现的非递归幂运算。我尝试在此处将其转换为Swift:

func expo(_ base: Int, _ power: Int) -> Int {
    var result = 1

    while (power != 0){
        if (power%2 == 1){
            result *= base
        }
        power /= 2
        base *= base
    }
    return result
}
当然,这可以通过创建一个重载操作符来调用它,然后可以重新编写它,使其更通用,这样它就可以处理任何实现
IntegerType
协议的事情

    func expo<T:IntegerType>(_ base: T, _ power: T) -> T {
    var result : T = 1
func expo(\ubase:T,\upower:T)->T{
var结果:T=1
但是,这一点可能被忽略了。

要计算功率(2,n)
,只需使用:

let result = 2 << (n-1)

let result=2事实证明,您也可以使用
pow()
。例如,您可以使用以下表达式表示10到9

pow(10, 9)

除了
pow
powf()
返回一个
float
,而不是
double
。我只在Swift 4和macOS 10.13上测试过这一点。

Swift 4.x版本

precedencegroup ExponentiationPrecedence {
  associativity: right
  higherThan: MultiplicationPrecedence
}

infix operator ^^: ExponentiationPrecedence
public func ^^ (radix: Float, power: Float) -> Float {
  return pow((radix), (power))
}

public func ^^ (radix: Double, power: Double) -> Double {
  return pow((radix), (power))
}

public func ^^ (radix: Int, power: Int) -> Int {
  return NSDecimalNumber(decimal: pow(Decimal(radix), power)).intValue
}

pow(10, 9)

precedencegroup ExponentiationPrecedence {
  associativity: right
  higherThan: MultiplicationPrecedence
}

infix operator ^^: ExponentiationPrecedence
public func ^^ (radix: Float, power: Float) -> Float {
  return pow((radix), (power))
}

public func ^^ (radix: Double, power: Double) -> Double {
  return pow((radix), (power))
}

public func ^^ (radix: Int, power: Int) -> Int {
  return NSDecimalNumber(decimal: pow(Decimal(radix), power)).intValue
}
extension Int{
    func expo(_ power: Int) -> Int {
        var result = 1
        var powerNum = power
        var tempExpo = self
        while (powerNum != 0){
        if (powerNum%2 == 1){
            result *= tempExpo
        }
        powerNum /= 2
        tempExpo *= tempExpo
        }
        return result
    }
}

2.expo(5) // pow(2, 5)
enum CustomMath<T: BinaryInteger> {

    static func pow(_ base: T, _ power: T) -> T {
        var tempBase = base
        var tempPower = power
        var result: T = 1

        while (power != 0) {
            if (power % 2 == 1) {
                result *= base
            }
            tempPower = tempPower >> 1
            tempBase *= tempBase
        }
        return result
    }
}
CustomMath.pow(1,1)
extension Int {   
    func pow(toPower: Int) -> Int {
        guard toPower > 0 else { return 0 }
        return Array(repeating: self, count: toPower).reduce(1, *)
    }
}

2.pow(toPower: 8) // returns 256