我们可以使用String Format说明符将整数值或long值转换为十六进制表示法。
Int Example:
print(String(format:"%x", 1111))
//result:457
Long Example:
print(String(format:"%lx", 11111111111111))
//result:a1b01d4b1c7
但是,如果我们尝试转换大于uint64.max的非常大的小数,该怎么办? // 18446744073709551615
在这种情况下转换的正确方法是什么?
答案 0 :(得分: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