swift - 在 Swift 中将 double 转换为十六进制表示法

标签 swift hex

如何将非常大的数字转换为十六进制?

例如,647751843213568900000 的十六进制为 0x231d5cd577654ceab3。我可以轻松地从十六进制变为两倍:

let hex: Double = 0x231d5cd577654ceab3

但是我无法弄清楚如何从 Double 返回到 hex。我错过了什么?

以下不起作用,因为它在存储为“Int”时会溢出:

let hexConverted = String(647751843213568900000, radix: 16)

最佳答案

基本算法(Swift 5)如下:

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 = Array(string)
            .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 时您的值是如何被截断的。

关于swift - 在 Swift 中将 double 转换为十六进制表示法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45057412/

相关文章:

将 c 十六进制值转换为 char*

c# - 如何在 C# 或 VB.NET 中格式化变量?

javascript - 以编程方式使十六进制颜色(或 rgb 和混合颜色)变亮或变暗

ios - 快速覆盖UIView的init方法

ios - 在 map 上查找城市或地区的多边形

ios - 尾随的滑动 Action 不会消失

ios - 如何去除大标题导航栏的底部边框?

internet-explorer - 一个reg如何通过批处理文件将十六进制值添加到Internet设置?

ios - CGPath 复制 lineJoin 和 miterLimit 没有明显影响

c++ - 1 字节整数不转换 i/o 格式