问题描述
我有位阵列:
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 = NUMBITS / 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 = NUMBITS / 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 arrayand 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 canuse index % 8
or 7 - index % 8
as shift amount, depending on thedesired 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 groupof 8 bits. You'll have to check which solution performs betterin 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数组)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!