如果 NSDecimalNumber 大于 Uint64,如何将 NSDecimalNumber 转换为字节数组?

How to convert NSDecimalNumber to byte array if NSDecimalNumber is bigger than Uint64?

我想将 NSDecimalNumber 转换为字节数组。另外,我不想为此使用任何库,例如 BigInt、BInt 等。

我试过这个:

static func toByteArray<T>(_ value: T) -> [UInt8] {
    var value = value
    return withUnsafeBytes(of: &value) { Array([=10=]) }
}
let value =  NSDecimalNumber(string: "...")
let bytes = toByteArray(value.uint64Value)

如果数字不大于Uint64,效果很好。但是,如果是,我们如何转换呢?

您超过了 value.uint64Value 而不是 value。因此,数字将 环绕 零以适应 NSDecimal 到 UInt64 格式。

"18446744073709551616"(也就是UInt64.max+1对应的字符串)等同于传"0"。传"18446744073709551617"(也就是UInt64.max+2对应的字符串)等同于传"1".

问题很明显是uint64Value的使用,显然不能表示任何大于UInt64.max的值,而你的例子59,785,897,542,892,656,787,456比那个大

如果你想获取128位尾数的字节表示,你可以使用_mantissa元组UInt16Decimal,如果你想把它们转换成字节.例如

extension Decimal {
    var byteArray: [UInt8] {
        return [_mantissa.0,
                _mantissa.1,
                _mantissa.2,
                _mantissa.3,
                _mantissa.4,
                _mantissa.5,
                _mantissa.6,
                _mantissa.7]
            .flatMap { [UInt8([=10=] & 0xff), UInt8([=10=] >> 8)] }
    }
}

if let foo = Decimal(string: "59785897542892656787456") {
    print(foo.byteArray)
}

返回:

[0, 0, 0, 0, 0, 0, 0, 0, 169, 12, 0, 0, 0, 0, 0, 0]

诚然,这只是推迟了问题,打破了您的 uint64Value 方法的 64 位限制,但仍然受限于 NSDecimalNumber/[=17 的固有 128 位限制=].要捕获大于 128 位的数字,您需要完全不同的表示法。


注意:这也假设指数是 0。但是,如果您有一些大数字,例如4.2e101 (4.2 * 10101),指数为 100,尾数为 42,我敢打赌这可能不是你想要的你的字节数组。再一次,这是一个太大而无法表示为单个 128 位整数的数字示例,无论如何:

if let foo = Decimal(string: "4.2e101") {
    print(foo.byteArray)
    print(foo.exponent)
}

产量:

[42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
100