Обратите внимание, что наиболее распространенные варианты использования битовых масок включают упаковку набора определенных значимых логических флагов в одно значение размером в слово и выполнение тестов для этих флагов. Swift предоставляет для этого средства типа OptionSet
.
struct Bits: OptionSet {
let rawValue: UInt // unsigned is usually best for bitfield math
init(rawValue: UInt) { self.rawValue = rawValue }
static let one = Bits(rawValue: 0b1)
static let two = Bits(rawValue: 0b10)
static let four = Bits(rawValue: 0b100)
static let eight = Bits(rawValue: 0b1000)
}
let someBits = Bits(rawValue: 13)
// the following all return true:
someBits.contains(.four)
someBits.isDisjoint(with: .two)
someBits == [.one, .four, .eight]
someBits == [.four, .four, .eight, .one] // set algebra: order/duplicates moot
someBits == Bits(rawValue: 0b1011)
(Конечно, в реальных условиях вы бы присвоили каждому из значений «элементов» в вашем типе OptionSet
какое-то значение, значимое для вашего варианта использования.)
OptionSet
на самом деле является одним значением (которое поддерживает алгебру множеств в терминах самого себя, а не в терминах типа элемента), поэтому это не коллекция, то есть она не предоставляет способ перечисления своих элементов. Но если то, как вы собираетесь использовать битовую маску, требует только установки и тестирования определенных флагов (или комбинаций флагов), возможно, вам не нужен способ перечисления элементов.
И если вам нужно перечислить элементы, но также нужны все функции набора алгебры OptionSet
, вы можете комбинировать OptionSet
с математикой с битовым разделением, например, найденной в ответ @rmaddy:
extension OptionSet where RawValue == UInt { // try being more generic?
var discreteElements: [Self] {
var result = [Self]()
var bitmask = self.rawValue
var element = RawValue(1)
while bitmask > 0 && element < ~RawValue.allZeros {
if bitmask & 0b1 == 1 {
result.append(Self(rawValue: element))
}
bitmask >>= 1
element <<= 1
}
return result
}
}
someBits.discreteElements.map({$0.rawValue}) // => [1, 4, 8]
person
rickster
schedule
30.11.2016
0b01001110
? Шестнадцатеричное значение0x01001110
имеет очень разные наборы битов, чем двоичное число0b01001110
. - person rmaddy   schedule 30.11.2016