斯威夫特位阵列字节数组(UINT8数组) [英] Swift Bit array to Bytes array (UInt8 array)

查看:149
本文介绍了斯威夫特位阵列字节数组(UINT8数组)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有位阵列:

  VAR位:[位]

和我怎么可能将其转换为字节数组:

 字节VAR:[UINT8]

例如我有280位,我应该在字节数组35 UINT8。我能想到的解决方案,我拿8位,并检查第一个是真实的,如果第二个是真实的,那么,总结的结果和具有价值。这个我会在我的阵位8位每做。但我认为这将是坏的解决方案(这是可行的但不必要的计算)。我想可能有一些转移等更快的解决方案,但我真的不好这个,所以我寻求帮助。谢谢


解决方案

一个可能的解决方案是枚举所有位在数组中
和所有的一位设置在相应的位 UINT8
数组:

  FUNC bitsToBytes(位:[位]) -  GT; [UINT8] {
    让NUMBITS = bits.count
    让我们的numBytes =(NUMBITS + 7)/ 8
    VAR字节= [UINT8](计数:的numBytes,repeatedValue:0)    在历数(位)(指数位){
        如果位== {。一
            字节[索引/ 8] + = 1<< (7 - 索引%8)
        }
    }    返回字节
}

其主要思想是,对于位阵列中的一个给定的首页
指数/ 8 是字节数组中的相应指数,
索引%8 是在字节的位位置。您可以
使用索引%8 7 - 指数8%的偏移量,取决于
所需的位顺序。

例如:

  // 0110 0100 0000 1001
让位:[位] = [.Zero,。一,。一,.Zero,.Zero,。一,.Zero,.Zero,.Zero,.Zero,.Zero,.Zero,。一,.Zero, .Zero,。一]
让字节= bitsToBytes(位)
的println(字节)// [100中,9]

或者的可以内联的计算每组
的8位。你必须检查哪些解决方案执行得更好
你的情况。

  FUNC bitsToBytes(位:[位]) -  GT; [UINT8] {
    让NUMBITS = bits.count
    让我们的numBytes = NUM​​BITS / 8
    VAR字节= [UINT8](计数:的numBytes,repeatedValue:0)
    在0 LT POS ..&; {的numBytes
        让VAL = 128 *位[8 * POS] .toIntMax()+
            64 *位[8 *位置pos + 1] .toIntMax()+
            32 *位[8 *位置pos + 2] .toIntMax()+
            16 *位[8 *位置pos + 3] .toIntMax()+
            8 *位[8 *位置pos + 4] .toIntMax()+
            4 *位[8 *位置pos + 5] .toIntMax()+
            2 *位[8 *位置pos + 6] .toIntMax()+
            1 *位[8 * POS + 7] .toIntMax()
        字节[POS] = UINT8(VAL)
    }
    返回字节
}

下面,为了简化,如果比特数不是8的倍数时,任何多余的位被忽略。同样的code也可以写一点
Swiftier为

  FUNC bitsToBytes(位:[位]) -  GT; [UINT8] {
    返回地图(0 ..< bits.count / 8){
        在POS机
        让VAL = 128 *位[8 * POS] .toIntMax()+
            64 *位[8 *位置pos + 1] .toIntMax()+
            32 *位[8 *位置pos + 2] .toIntMax()+
            16 *位[8 *位置pos + 3] .toIntMax()+
            8 *位[8 *位置pos + 4] .toIntMax()+
            4 *位[8 *位置pos + 5] .toIntMax()+
            2 *位[8 *位置pos + 6] .toIntMax()+
            1 *位[8 * POS + 7] .toIntMax()
        回报(UINT8(VAL))
    }
}


测试:这里现在是一个快速和肮脏的基准程序(code以下),比较各种方案。
它测量转换长度为256 10,000位阵列的时间。
这些测试是在MacBook Pro上2,3 GHz的英特尔酷睿i7完成,
和code。与发行配置编译。

与雨燕1.1 / X code 6.2(6C131e)结果


Martin1:0.0460730195045471
Martin2:0.0280380249023438
Martin3:0.0374950170516968
安东尼:5.85363000631332
内特:4.86936402320862

与雨燕1.2 / X code 6.3(6D532l)结果


Martin1:0.0228430032730103
Martin2:0.00573796033859253
Martin3:0.00732702016830444
安东尼:0.515677988529205
内特:0.634827971458435

code:

 协议BitsToBytesConverter {
    VAR的ident:字符串{}获取
    FUNC bitsToBytes(位:[位]) - GT; [UINT8]
}类MR1:BitsToBytesConverter {    让IDENT =Martin1
    FUNC bitsToBytes(位:[位]) - GT; [UINT8] {
        让NUMBITS = bits.count
        让我们的numBytes =(NUMBITS + 7)/ 8
        VAR字节= [UINT8](计数:的numBytes,repeatedValue:0)        在历数(位)(指数位){
            如果位== {。一
                字节[索引/ 8] + = UINT8(1 LT;<(7 - 索引%8))
            }
        }        返回字节
    }
}类MR2:BitsToBytesConverter {    让IDENT =Martin2    FUNC bitsToBytes(位:[位]) - GT; [UINT8] {
        让NUMBITS = bits.count
        让我们的numBytes = NUM​​BITS / 8
        VAR字节= [UINT8](计数:的numBytes,repeatedValue:0)
        在0 LT POS ..&; {的numBytes
            让VAL = 128 *位[8 * POS] .toIntMax()+
                64 *位[8 *位置pos + 1] .toIntMax()+
                32 *位[8 *位置pos + 2] .toIntMax()+
                16 *位[8 *位置pos + 3] .toIntMax()+
                8 *位[8 *位置pos + 4] .toIntMax()+
                4 *位[8 *位置pos + 5] .toIntMax()+
                2 *位[8 *位置pos + 6] .toIntMax()+
                1 *位[8 * POS + 7] .toIntMax()
            字节[POS] = UINT8(VAL)
        }
        返回字节
    }
}类MR3:BitsToBytesConverter {    让IDENT =Martin3    FUNC bitsToBytes(位:[位]) - GT; [UINT8] {
        返回地图(0 ..< bits.count / 8){
            在POS机
            让VAL = 128 *位[8 * POS] .toIntMax()+
                64 *位[8 *位置pos + 1] .toIntMax()+
                32 *位[8 *位置pos + 2] .toIntMax()+
                16 *位[8 *位置pos + 3] .toIntMax()+
                8 *位[8 *位置pos + 4] .toIntMax()+
                4 *位[8 *位置pos + 5] .toIntMax()+
                2 *位[8 *位置pos + 6] .toIntMax()+
                1 *位[8 * POS + 7] .toIntMax()
            回报(UINT8(VAL))
        }
    }
}AB类:BitsToBytesConverter {    让IDENT =安东尼奥    typealias IntegerType = UINT8    FUNC bitsToBytes(位:[位]) - GT; [UINT8] {        让初始= [IntegerType]()        返回减少(枚举(比特),初始){数组元素中
            //在UINT8的位大小
            让大小= sizeof的(IntegerType)* 8            //数组的创建一个可变的副本在previous迭代中返回
            VAR下一=阵列            //如果它的第一次迭代,或通过UINT8的尺寸整除迭代,
            //一个新元素追加到数组
            如果element.index%大小== 0 {
                next.append(0×00)
            }            //移的最后一个元素的所有位向左
            接下来[next.count - 1];< = 1            //如果当前位为1,加入1到最右边的位
            //使用逻辑OR
            如果element.element == {。一
                接下来[next.count - 1] | = 0×01
            }            下一回
        }
    }
}类NC:BitsToBytesConverter {    让IDENT =内特    FUNC组< T>(数组:[T],​​byCount groupCount的:int) - GT; [快讯< T>] {
        //获取开始指数列表
        让startIndices =步幅(从0到:array.count,通过:groupCount)
        //添加`groupCount`每个获得最终指数
        让endIndices =懒惰(startIndices).MAP {前进($ 0 groupCount,array.count)}        //压缩那些一起放&;映射到输入阵列的片阵列
        返回地图(ZIP2(startIndices,endIndices)){
            数组[$ 0.0次..< $ 0.1]
        }
    }    FUNC bitsToByte(位:切片<位>) - GT; UINT8 {
        返回bits.reduce(0){积累,目前在
            积累<< 1 | (电流==。一?1:0)
        }
    }    FUNC bitsToBytes(位:[位]) - GT; [UINT8] {
        返回组(位,byCount:8).MAP(bitsToByte)
    }
}
让NUMBITS = 256 //每比特位阵列
让numBitArrays = 10000 //位阵列数FUNC randomBits() - > [位] {
    返回地图(0 ..< NUMBITS){_中
        位(rawValue:INT(arc4random_uniform(2)))!
    }
}FUNC randomBitsArray() - > [位]] {
    返回地图(0 ..< numBitArrays){_中
        randomBits()
    }
}让bitsArray = randomBitsArray()FUNC测试(CONV:BitsToBytesConverter){
    令x = conv.bitsToBytes([])
    让STARTTIME = NSDate的()
    在bitsArray位{
        让字节= conv.bitsToBytes(位)
    }
    让时间= -startTime.timeIntervalSinceNow
    的println(\\(conv.ident):\\(持续时间))
}试验(MR1())
试验(MR2())
试验(MR3())
测试(AB())
测试(NC())

I have array with bits:

var bits: [Bit]

and how could I convert it to bytes array:

var bytes: [UInt8]

For example I have 280 bits and I should have 35 UInt8 in bytes array. I can think of solution where I take 8bits and check if first is true, if second is true and so and sum the results and have value. This I would do for every 8bits in my bits array. But I think this would be bad solution (it would work but with unnecessary calculations). I think there could be faster solution with some shifting and so but I am really bad in this so I am looking for help. Thanks

解决方案

A possible solution is to enumerate all bits in the array and for all "One" bits set the corresponding bit in the UInt8 array:

func bitsToBytes(bits: [Bit]) -> [UInt8] {
    let numBits = bits.count
    let numBytes = (numBits + 7)/8
    var bytes = [UInt8](count : numBytes, repeatedValue : 0)

    for (index, bit) in enumerate(bits) {
        if bit == .One {
            bytes[index / 8] += 1 << (7 - index % 8)
        }
    }

    return bytes
}

The main idea is that for a given index in the bit array, index / 8 is the corresponding index in the byte array, and index % 8 is the bit position in the byte. You can use index % 8 or 7 - index % 8 as shift amount, depending on the desired bit order.

Example:

// 0110 0100  0000 1001
let bits : [Bit] = [.Zero, .One, .One, .Zero,  .Zero, .One, .Zero, .Zero,  .Zero, .Zero, .Zero, .Zero,  .One, .Zero, .Zero, .One]
let bytes = bitsToBytes(bits)
println(bytes) // [100, 9]

Alternatively, you can "inline" the calculation for each group of 8 bits. You'll have to check which solution performs better in your case.

func bitsToBytes(bits: [Bit]) -> [UInt8] {
    let numBits = bits.count
    let numBytes = numBits/8
    var bytes = [UInt8](count : numBytes, repeatedValue : 0)
    for pos in 0 ..< numBytes {
        let val = 128 * bits[8 * pos].toIntMax() + 
            64 * bits[8 * pos + 1].toIntMax() +
            32 * bits[8 * pos + 2].toIntMax() +
            16 * bits[8 * pos + 3].toIntMax() +
            8 * bits[8 * pos + 4].toIntMax() +
            4 * bits[8 * pos + 5].toIntMax() +
            2 * bits[8 * pos + 6].toIntMax() +
            1 * bits[8 * pos + 7].toIntMax()
        bytes[pos] = UInt8(val)
    }
    return bytes
}

Here, for simplicity, if the number of bits is not a multiple of 8, any excess bits are ignored. The same code can also be written a bit "Swiftier" as

func bitsToBytes(bits: [Bit]) -> [UInt8] {
    return map(0 ..< bits.count/8) {
        pos in
        let val = 128 * bits[8 * pos].toIntMax() + 
            64 * bits[8 * pos + 1].toIntMax() +
            32 * bits[8 * pos + 2].toIntMax() +
            16 * bits[8 * pos + 3].toIntMax() +
            8 * bits[8 * pos + 4].toIntMax() +
            4 * bits[8 * pos + 5].toIntMax() +
            2 * bits[8 * pos + 6].toIntMax() +
            1 * bits[8 * pos + 7].toIntMax()
        return (UInt8(val))
    }
}


Benchmarks: Here is now a quick-and-dirty benchmarking app (code below), comparing the various solutions. It measures the time to convert 10,000 bit arrays of length 256. The tests were done on a MacBook Pro 2,3 GHz Intel Core i7, and the code compiled with the "Release" configuration.

Results with Swift 1.1/Xcode 6.2 (6C131e):

Martin1: 0.0460730195045471
Martin2: 0.0280380249023438
Martin3: 0.0374950170516968
Antonio: 5.85363000631332
Nate   : 4.86936402320862

Results with Swift 1.2/Xcode 6.3 (6D532l):

Martin1: 0.0228430032730103
Martin2: 0.00573796033859253
Martin3: 0.00732702016830444
Antonio: 0.515677988529205
Nate   : 0.634827971458435

Code:

protocol BitsToBytesConverter {
    var ident : String { get }
    func bitsToBytes(bits: [Bit]) -> [UInt8]
}

class MR1 : BitsToBytesConverter {

    let ident = "Martin1"
    func bitsToBytes(bits: [Bit]) -> [UInt8] {
        let numBits = bits.count
        let numBytes = (numBits + 7)/8
        var bytes = [UInt8](count : numBytes, repeatedValue : 0)

        for (index, bit) in enumerate(bits) {
            if bit == .One {
                bytes[index / 8] += UInt8(1 << (7 - index % 8))
            }
        }

        return bytes
    }
}

class MR2 : BitsToBytesConverter {

    let ident = "Martin2"

    func bitsToBytes(bits: [Bit]) -> [UInt8] {
        let numBits = bits.count
        let numBytes = numBits/8
        var bytes = [UInt8](count : numBytes, repeatedValue : 0)
        for pos in 0 ..< numBytes {
            let val = 128 * bits[8 * pos].toIntMax() + 
                64 * bits[8 * pos + 1].toIntMax() +
                32 * bits[8 * pos + 2].toIntMax() +
                16 * bits[8 * pos + 3].toIntMax() +
                8 * bits[8 * pos + 4].toIntMax() +
                4 * bits[8 * pos + 5].toIntMax() +
                2 * bits[8 * pos + 6].toIntMax() +
                1 * bits[8 * pos + 7].toIntMax()
            bytes[pos] = UInt8(val)
        }
        return bytes
    }
}

class MR3 : BitsToBytesConverter {

    let ident = "Martin3"

    func bitsToBytes(bits: [Bit]) -> [UInt8] {
        return map(0 ..< bits.count/8) {
            pos in
            let val = 128 * bits[8 * pos].toIntMax() + 
                64 * bits[8 * pos + 1].toIntMax() +
                32 * bits[8 * pos + 2].toIntMax() +
                16 * bits[8 * pos + 3].toIntMax() +
                8 * bits[8 * pos + 4].toIntMax() +
                4 * bits[8 * pos + 5].toIntMax() +
                2 * bits[8 * pos + 6].toIntMax() +
                1 * bits[8 * pos + 7].toIntMax()
            return (UInt8(val))
        }
    }
}

class AB : BitsToBytesConverter {

    let ident = "Antonio"

    typealias IntegerType = UInt8

    func bitsToBytes(bits: [Bit]) -> [UInt8] {

        let initial = [IntegerType]()

        return reduce(enumerate(bits), initial) { array, element in
            // The size in bits of a UInt8
            let size = sizeof(IntegerType) * 8

            // Create a mutable copy of the array returned at the previous iteration
            var next = array

            // If it's the first iteration, or an iteration divisible by the size of UInt8, 
            // append a new element to the array
            if element.index % size == 0 {
                next.append(0x00)
            }

            // Shift all bits of the last element to the left
            next[next.count - 1] <<= 1

            // If the current bit is one, add 1 to the rightmost bit
            // Using a logical OR
            if element.element == .One {
                next[next.count - 1] |= 0x01
            }

            return next
        }
    }
}

class NC : BitsToBytesConverter {

    let ident = "Nate   "

    func group<T>(array: [T], byCount groupCount: Int) -> [Slice<T>] {
        // get a list of the start indices
        let startIndices = stride(from: 0, to: array.count, by: groupCount)
        // add `groupCount` to each to get the end indices
        let endIndices = lazy(startIndices).map { advance($0, groupCount, array.count) }

        // zip those together & map onto an array of slices of the input array
        return map(Zip2(startIndices, endIndices)) {
            array[$0.0 ..< $0.1]
        }
    }

    func bitsToByte(bits: Slice<Bit>) -> UInt8 {
        return bits.reduce(0) { accumulated, current in
            accumulated << 1 | (current == .One ? 1 : 0)
        }
    }

    func bitsToBytes(bits: [Bit]) -> [UInt8] {
        return group(bits, byCount: 8).map(bitsToByte)
    }
}


let numBits = 256 // Bits per bit array
let numBitArrays = 10000 // Number of bit arrays

func randomBits() -> [Bit] {
    return map(0 ..< numBits) { _  in
        Bit(rawValue: Int(arc4random_uniform(2)))!
    }
}

func randomBitsArray() -> [[Bit]] {
    return map(0 ..< numBitArrays) { _ in
        randomBits()
    }
}

let bitsArray = randomBitsArray()

func test(conv : BitsToBytesConverter) {
    let x = conv.bitsToBytes([])
    let startTime = NSDate()
    for bits in bitsArray {
        let bytes = conv.bitsToBytes(bits)
    }
    let duration = -startTime.timeIntervalSinceNow
    println("\(conv.ident): \(duration)")
}

test(MR1())
test(MR2())
test(MR3())
test(AB())
test(NC())

这篇关于斯威夫特位阵列字节数组(UINT8数组)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆