繁体   English   中英

快速将十进制字符串转换为UInt8-Array

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM