【问题标题】:How to handle answer of long long integers in swift [duplicate]如何快速处理长整数的答案[重复]
【发布时间】:2019-01-24 11:01:13
【问题描述】:

我必须快速计算两个长整数的幂。 Swift 给出一个 NaN(不是数字)的错误并且无法回答。

例如

战俘(2907,1177)

计算幂取余数的主进程id(a^b % n) where a= 2907, b= 1177, n= 1211

任何指导如何解决它?

【问题讨论】:

  • pow 仅适用于浮点,NaN 是 IEEE 754 浮点“值”。
  • 此外,您似乎正在尝试执行Modular exponentiation,并且为此提供了特殊的Memory-efficient method。您根本不需要计算a^b 的全部价值。
  • @Mubashar,如果它适合你,请不要犹豫接受答案。

标签: swift rsa long-integer modulus pow


【解决方案1】:

您将不得不使用 1. 外部框架或 2. 自己做。

1.外部框架

我想你可以试试:https://github.com/mkrd/Swift-Big-Integer

let a = BInt(2907)
let b = 1177
let n = BInt(1211)

let result = (a ** b) % n

print(result) // prints 331

注意:Cocoapods 导入失败,所以我只导入了这个文件以使其工作:https://github.com/mkrd/Swift-Big-Integer/tree/master/Sources

2。自己动手做: 使用Modulus power of big numbers的答案

func powerMod(base: Int, exponent: Int, modulus: Int) -> Int {
    guard base > 0 && exponent >= 0 && modulus > 0
        else { return -1 }

    var base = base
    var exponent = exponent
    var result = 1

    while exponent > 0 {
        if exponent % 2 == 1 {
            result = (result * base) % modulus
        }
        base = (base * base) % modulus
        exponent = exponent / 2
    }

    return result
}

let result = powerMod(base: 2907, exponent: 1177, modulus: 1211)

print(result) // prints 331

3.奖励:使用与 2 相同的方法。但由于 http://natecook.com/blog/2014/10/ternary-operators-in-swift/

,使用了自定义三元运算符
precedencegroup ModularityLeft {
    higherThan: ComparisonPrecedence
    lowerThan: AdditionPrecedence
}

precedencegroup ModularityRight {
    higherThan: ModularityLeft
    lowerThan: AdditionPrecedence
}

infix operator *%* : ModularityLeft
infix operator %*% : ModularityRight

func %*%(exponent: Int, modulus: Int) -> (Int) -> Int {
    return { base in
        guard base > 0 && exponent >= 0 && modulus > 0
            else { return -1 }

        var base = base
        var exponent = exponent
        var result = 1

        while exponent > 0 {
            if exponent % 2 == 1 {
                result = (result * base) % modulus
            }
            base = (base * base) % modulus
            exponent = exponent / 2
        }

        return result
    }
}

func *%*(lhs: Int, rhs: (Int) -> Int) -> Int {
    return rhs(lhs)
}

然后你就可以打电话了:

let result = 2907 *%* 1177 %*% 1211

其他信息: 仅用于二进制 2907^1177 的信息需要 13542 位... https://www.wolframalpha.com/input/?i=2907%5E1177+in+binary

需要一个 4kb 的字符串来存储它以 10 为底:https://www.wolframalpha.com/input/?i=2907%5E1177

【讨论】:

  • 第二点。 DIY:使用大数模幂的答案是获得长数模数的正确选择。
猜你喜欢
  • 1970-01-01
  • 2021-06-24
  • 2016-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-06
相关资源
最近更新 更多