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

时间:2015-06-10 16:42:41

标签: ios swift type-conversion

我有一个非常长的字符串(600多个字符),持有一个大的十进制值(是的,我知道 - 听起来像一个BigInteger),需要这个值的字节表示。

有没有简单的方法可以使用swift存档?

static func decimalStringToUInt8Array(decimalString:String) -> [UInt8] {
  ...
}

4 个答案:

答案 0 :(得分:2)

我写了一个函数来转换你的数字字符串。这是用Swift 1.2编写的。

func decimalStringToUInt8Array(decimalString:String) -> [UInt8] {

    // Convert input string into array of Int digits
    let digits = Array(decimalString).map{String($0).toInt()!}
    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 aren't a multiple of 6 digits in the number.
    var ints:[Int] = Array(count: (numdigits + 5)/6, repeatedValue: 0)
    var rem = numdigits % 6
    if rem == 0 {
        rem = 6
    }
    var index = 0
    var accum = 0
    for digit in digits {
        accum = accum * 10 + digit
        if --rem == 0 {
            rem = 6
            ints[index++] = accum
            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 enumerate(ints) {
            var total = carry * 1000000 + value
            carry = total % 256
            total /= 256
            ints[index] = total
        }

        bytes.append(UInt8(truncatingBitPattern: carry))

        // Remove leading Ints that have become zero.
        while ints.count > 0 && ints[0] == 0 {
            ints.removeAtIndex(0)
        }
    }

    // Reverse the array and return it
    return reverse(bytes)
}

println(decimalStringToUInt8Array("0"))         // prints "[0]"
println(decimalStringToUInt8Array("255"))       // prints "[255]"
println(decimalStringToUInt8Array("256"))       // prints "[1,0]"
println(decimalStringToUInt8Array("1024"))      // prints "[4,0]"
println(decimalStringToUInt8Array("16777216"))  // prints "[1,0,0,0]"

这是反向功能。你会发现它非常相似:

func uInt8ArrayToDecimalString(uint8array:[UInt8]) -> String {

    // For efficiency in calculation, combine 3 bytes into one Int.
    let numvalues = uint8array.count
    var ints:[Int] = Array(count: (numvalues + 2)/3, repeatedValue: 0)
    var rem = numvalues % 3
    if rem == 0 {
        rem = 3
    }
    var index = 0
    var accum = 0
    for value in uint8array {
        accum = accum * 256 + Int(value)
        if --rem == 0 {
            rem = 3
            ints[index++] = accum
            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 enumerate(ints) {
            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.removeAtIndex(0)
        }
    }

    // Reverse the digits array, convert them to String, and join them
    return join("", digits.reverse().map{String($0)})
}

进行往返测试以确保我们回到我们开始的地方:

let a = "1234567890987654321333555777999888666444222000111"
let b = decimalStringToUInt8Array(a)
let c = uInt8ArrayToDecimalString(b)
if a == c {
    println("success")
} else {
    println("failure")
}
  

结果:“成功”

答案 1 :(得分:1)

您可以使用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)
}
}

答案 2 :(得分:0)

你总是可以这样做:

let bytes = [UInt8](decimalString.utf8)

如果你想要UTF-8字节。

答案 3 :(得分:0)

如果您在十进制字符串上实现了除法,则可以重复除以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]--);
}