【问题标题】:Converting very large decimal numbers to hexadecimal in swift快速将非常大的十进制数转换为十六进制
【发布时间】:2018-05-24 22:46:58
【问题描述】:

我们可以使用字符串格式说明符将整数值或长整数值转换为十六进制表示法。

Int Example:
print(String(format:"%x", 1111))
//result:457

Long Example:        
print(String(format:"%lx", 11111111111111))
//result:a1b01d4b1c7

但是,如果我们尝试转换一个大于 uint64.max 的非常大的小数呢? //18446744073709551615

在这种情况下,正确的转换方式是什么?

【问题讨论】:

    标签: swift hex biginteger


    【解决方案1】:

    一种可能的解决方案是使用NSDecimalNumber 来保存较大的值。但它没有任何内置方法可以将数字转换为以 10 为底的字符串。

    以下是 NSDecimalNumber 的扩展,它将数字转换为从 2 到 16 的任何基数。它还包括一个方便的 init,它接受一个给定基数的字符串。

    extension NSDecimalNumber {
        convenience init(string: String, base: Int) {
            guard base >= 2 && base <= 16 else { fatalError("Invalid base") }
    
            let digits = "0123456789ABCDEF"
            let baseNum = NSDecimalNumber(value: base)
    
            var res = NSDecimalNumber(value: 0)
            for ch in string {
                let index = digits.index(of: ch)!
                let digit = digits.distance(from: digits.startIndex, to: index)
                res = res.multiplying(by: baseNum).adding(NSDecimalNumber(value: digit))
            }
    
            self.init(decimal: res.decimalValue)
        }
    
        func toBase(_ base: Int) -> String {
            guard base >= 2 && base <= 16 else { fatalError("Invalid base") }
    
            // Support higher bases by added more digits
            let digits = "0123456789ABCDEF"
            let rounding = NSDecimalNumberHandler(roundingMode: .down, scale: 0, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: false)
            let baseNum = NSDecimalNumber(value: base)
    
            var res = ""
            var val = self
            while val.compare(0) == .orderedDescending {
                let next = val.dividing(by: baseNum, withBehavior: rounding)
                let round = next.multiplying(by: baseNum)
                let diff = val.subtracting(round)
                let digit = diff.intValue
                let index = digits.index(digits.startIndex, offsetBy: digit)
                res.insert(digits[index], at: res.startIndex)
    
                val = next
            }
    
            return res
        }
    }
    

    测试:

    let bigNum = NSDecimalNumber(string: "18446744073709551615")
    print(bigNum.toBase(16))
    print(bigNum.toBase(10)) // or just print(bigNum)
    print(NSDecimalNumber(string: "B7", base: 16))
    print(NSDecimalNumber(string: NSDecimalNumber(string: "18446744073709551615").toBase(16), base: 16))
    

    输出:

    FFFFFFFFFFFFFFFF
    18446744073709551615
    183
    18446744073709551615

    【讨论】:

    • 非常聪明的@rmaddy
    猜你喜欢
    • 1970-01-01
    • 2010-10-31
    • 1970-01-01
    • 1970-01-01
    • 2019-01-27
    • 2015-06-25
    • 2016-01-07
    • 2015-01-26
    • 1970-01-01
    相关资源
    最近更新 更多