我有位数组:
var bits: [Bit]
以及如何将其转换为字节数组:
var bytes: [UInt8]
例如,我有280位,我应该有35个UInt8字节数组.我可以想到解决方案,我拿8位并检查第一个是否为真,如果第二个为真,那么总和结果并有价值.我会为我的位数组中的每8位做一次.但我认为这将是一个糟糕的解决方案(它可以工作,但有不必要的计算).我认为可能有更快的解决方案,有一些转移,所以但我真的很糟糕,所以我正在寻求帮助.谢谢
一种可能的解决方案是枚举数组中的所有位
并且对于所有“One”位设置UInt8中的相应位
数组:
并且对于所有“One”位设置UInt8中的相应位
数组:
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 }
主要思想是对于位数组中的给定索引,
index / 8是字节数组中的对应索引,
和索引%8是字节中的位位置.您可以
使用指数%8或7 – 指数%8作为转移金额,具体取决于
所需的位顺序.
例:
// 0110 0100 0000 1001 let bits : [Bit] = [.Zero,.One,.Zero,.One] let bytes = bitsToBytes(bits) println(bytes) // [100,9]
或者,您可以“内联”每个组的计算
8位您必须检查哪种解决方案表现更好
在你的情况下.
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 }
这里,为简单起见,如果位数不是8的倍数,则忽略任何多余的位.相同的代码也可以写一点
“斯威夫特”为
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)) } }
基准:现在是一个快速而肮脏的基准测试应用程序(下面的代码),比较各种解决方案.
它测量转换长度为256的10,000位数组的时间.
测试是在MacBook Pro 2,3 GHz Intel Core i7上完成的,
以及使用“Release”配置编译的代码.
Swift 1.1 / Xcode 6.2(6C131e)的结果:
Martin1: 0.0460730195045471 Martin2: 0.0280380249023438 Martin3: 0.0374950170516968 Antonio: 5.85363000631332 Nate : 4.86936402320862
Swift 1.2 / Xcode 6.3(6D532l)的结果:
Martin1: 0.0228430032730103 Martin2: 0.00573796033859253 Martin3: 0.00732702016830444 Antonio: 0.515677988529205 Nate : 0.634827971458435
码:
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())
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。