[英]Swift convert decimal String to UInt8-Array
我有一个非常长的String(600多个字符),其中包含一个大十进制值(是的,我知道-听起来像BigInteger),并且需要此值的字节表示形式。
有什么简单的方法可以迅速将其存档?
static func decimalStringToUInt8Array(decimalString:String) -> [UInt8] {
...
}
编辑:为Swift 5更新
我给你写了一个函数来转换你的数字字符串。 这是用Swift 5(最初是Swift 1.2)编写的。
func decimalStringToUInt8Array(_ decimalString: String) -> [UInt8] {
// Convert input string into array of Int digits
let digits = Array(decimalString).compactMap { Int(String($0)) }
// Nothing to process? Return an empty array.
guard digits.count > 0 else { return [] }
let numdigits = digits.count
// Array to hold the result, in reverse order
var bytes = [UInt8]()
// Convert array of digits into array of Int values each
// representing 6 digits of the original number. Six digits
// was chosen to work on 32-bit and 64-bit systems.
// Compute length of first number. It will be less than 6 if
// there isn't a multiple of 6 digits in the number.
var ints = Array(repeating: 0, count: (numdigits + 5)/6)
var rem = numdigits % 6
if rem == 0 {
rem = 6
}
var index = 0
var accum = 0
for digit in digits {
accum = accum * 10 + digit
rem -= 1
if rem == 0 {
rem = 6
ints[index] = accum
index += 1
accum = 0
}
}
// Repeatedly divide value by 256, accumulating the remainders.
// Repeat until original number is zero
while ints.count > 0 {
var carry = 0
for (index, value) in ints.enumerated() {
var total = carry * 1000000 + value
carry = total % 256
total /= 256
ints[index] = total
}
bytes.append(UInt8(truncatingIfNeeded: carry))
// Remove leading Ints that have become zero.
while ints.count > 0 && ints[0] == 0 {
ints.remove(at: 0)
}
}
// Reverse the array and return it
return bytes.reversed()
}
print(decimalStringToUInt8Array("0")) // prints "[0]"
print(decimalStringToUInt8Array("255")) // prints "[255]"
print(decimalStringToUInt8Array("256")) // prints "[1,0]"
print(decimalStringToUInt8Array("1024")) // prints "[4,0]"
print(decimalStringToUInt8Array("16777216")) // prints "[1,0,0,0]"
这是反向功能。 您会发现它非常相似:
func uInt8ArrayToDecimalString(_ uint8array: [UInt8]) -> String {
// Nothing to process? Return an empty string.
guard uint8array.count > 0 else { return "" }
// For efficiency in calculation, combine 3 bytes into one Int.
let numvalues = uint8array.count
var ints = Array(repeating: 0, count: (numvalues + 2)/3)
var rem = numvalues % 3
if rem == 0 {
rem = 3
}
var index = 0
var accum = 0
for value in uint8array {
accum = accum * 256 + Int(value)
rem -= 1
if rem == 0 {
rem = 3
ints[index] = accum
index += 1
accum = 0
}
}
// Array to hold the result, in reverse order
var digits = [Int]()
// Repeatedly divide value by 10, accumulating the remainders.
// Repeat until original number is zero
while ints.count > 0 {
var carry = 0
for (index, value) in ints.enumerated() {
var total = carry * 256 * 256 * 256 + value
carry = total % 10
total /= 10
ints[index] = total
}
digits.append(carry)
// Remove leading Ints that have become zero.
while ints.count > 0 && ints[0] == 0 {
ints.remove(at: 0)
}
}
// Reverse the digits array, convert them to String, and join them
return digits.reversed().map(String.init).joined()
}
做一次往返测试以确保我们回到开始的地方:
let a = "1234567890987654321333555777999888666444222000111"
let b = decimalStringToUInt8Array(a)
let c = uInt8ArrayToDecimalString(b)
if a == c {
print("success")
} else {
print("failure")
}
success
检查八个255
字节是否与UInt64.max
相同:
print(uInt8ArrayToDecimalString([255, 255, 255, 255, 255, 255, 255, 255]))
print(UInt64.max)
18446744073709551615 18446744073709551615
您可以使用NSData(int: Int, size: Int)
方法将一个Int转换为NSData,然后将字节从NSData转换为一个数组: [UInt8]
。
一旦知道了,唯一的事情就是知道数组的大小。 达尔文(Darwin)具有pow
功能,非常方便。 这是一个工作示例:
func stringToUInt8(string: String) -> [UInt8] {
if let int = string.toInt() {
let power: Float = 1.0 / 16
let size = Int(floor(powf(Float(int), power)) + 1)
let data = NSData(bytes: &int, length: size)
var b = [UInt8](count: size, repeatedValue: 0)
return data.getBytes(&b, length: size)
}
}
您可以随时这样做:
let bytes = [UInt8](decimalString.utf8)
如果要使用UTF-8字节。
如果您对十进制字符串实现了除法,则可以重复除以256。 第一次除法的提醒是您的最低有效字节。
这是一个用C进行标量除法的示例(假设数字的长度存储在A [0]中,并将结果写入同一数组中):
void div(int A[], int B)
{
int i, t = 0;
for (i = A[0]; i > 0; i--, t %= B)
A[i] = (t = t * 10 + A[i]) / B;
for (; A[0] > 1 && !A[A[0]]; A[0]--);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.