如果 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
元组UInt16
字Decimal
,如果你想把它们转换成字节.例如
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
我想将 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
元组UInt16
字Decimal
,如果你想把它们转换成字节.例如
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