如何将非常大的数字转换为十六进制?
例如,164751843213568900000(十六进制)为0x231d5cd577654ceab3。我可以轻松地从十六进制变为双精度:
let hex: Double = 0x231d5cd577654ceab3
但是我无法弄清楚如何从双回到十六进制。我错过了什么?
以下不起作用,因为它存储为'Int'时溢出:
let hexConverted = String(647751843213568900000, radix: 16)
答案 0 :(得分:4)
基本算法(Swift 4)如下:
func representationOf<T: FixedWidthInteger>(_ number: T, base: T) -> String {
var buffer: [Int] = []
var n = number
while n > 0 {
buffer.append(Int(n % base))
n /= base
}
return buffer
.reversed()
.map { String($0, radix: Int(base)) }
.joined()
}
print(representationOf(647751843213568900, base: 16))
当然,这是String(_:radix:)
正在做的事情,所以我们不需要自己实施。
你真正的问题不是编码,而是大整数的表示。
已经有多种实现,例如https://github.com/mkrd/Swift-Big-Integer。其中一些已经具有十六进制编码功能。
在Swift 4中,可以声明自己的更高 IntXXX
的实现(符合FixedWidthInteger
),问题会变得容易一些:
typealias Int128 = DoubleWidth<Int64>
typealias Int256 = DoubleWidth<Int128>
let longNumber = Int256("231d5cd577654ceab3", radix: 16)!
print(longNumber)
print(String(longNumber, radix: 16))
但不幸的是, DoubleWidth
尚未在Xcode 9 Beta 4中实现。
对于某些值,您也可以使用Decimal
类型。使用上面写的算法:
extension Decimal {
func rounded(mode: NSDecimalNumber.RoundingMode) -> Decimal {
var this = self
var result = Decimal()
NSDecimalRound(&result, &this, 0, mode)
return result
}
func integerDivisionBy(_ operand: Decimal) -> Decimal{
let result = (self / operand)
return result.rounded(mode: result < 0 ? .up : .down)
}
func truncatingRemainder(dividingBy operand: Decimal) -> Decimal {
return self - self.integerDivisionBy(operand) * operand
}
}
extension Decimal {
init(_ string: String, base: Int) {
var decimal: Decimal = 0
let digits = string.characters
.map { String($0) }
.map { Int($0, radix: base)! }
for digit in digits {
decimal *= Decimal(base)
decimal += Decimal(digit)
}
self.init(string: decimal.description)!
}
}
func representationOf(_ number: Decimal, base: Decimal) -> String {
var buffer: [Int] = []
var n = number
while n > 0 {
buffer.append((n.truncatingRemainder(dividingBy: base) as NSDecimalNumber).intValue)
n = n.integerDivisionBy(base)
}
return buffer
.reversed()
.map { String($0, radix: (base as NSDecimalNumber).intValue ) }
.joined()
}
let number = Decimal("231d5cd577654ceab3", base: 16)
print(number) // 647751843213568961203
print(representationOf(number, base: 16)) // 231d5cd577654ceab3
请注意转换为Double
后,您的值是如何被截断的。
答案 1 :(得分:1)
这是我的解决方案:
func toHex(number : Double) -> String
{
var n = number;
var reminders : [Double] = [];
while true
{
let reminder = n % 16;
n = floor(n/16.0);
reminders.append(reminder);
if(n == 0.0)
{
break;
}
}
var hex = "";
var i = reminders.count-1;
while(i > -1)
{
hex = hex + hexChar(reminders[i]);
i = i-1;
}
return hex;
}
func hexChar(n : Double) -> String
{
switch n
{
case 15: return "F";
case 14: return "E";
case 13: return "D";
case 12: return "C";
case 11: return "B";
case 10: return "A";
default: return String(Int(n))
}
}
toHex(647751843213568900000.0); //231D5CD577654C0000