从2个UINT8S创建一个UINT16



为了说明一个概念以后用于诸如UInt128UInt256之类的较大数据类型,我正在尝试执行以下功能:

我的功能采用2 UInt8 s,将第一个(理论上的位置更重要)移至左8,然后添加 int2(理论上是较低的位)

func combineBits(int1: UInt8, int2: UInt8) -> UInt16 {
   let x: UInt16 = (int1 << 8) + int2
   return x
}

我需要做一些事情来避免错误:(int1 << 8) + int2不等于指定的类型UInt16

您必须显式将较小的类型转换为较大类型:

func combineBits(int1: UInt8, int2: UInt8) -> UInt16 {
    let x: UInt16 = (UInt16(int1) << 8) + UInt16(int2)
    return x
}

这也使显式类型注释不必要:

func combineBits(int1: UInt8, int2: UInt8) -> UInt16 {
    let x = (UInt16(int1) << 8) + UInt16(int2)
    return x
}

可以缩短为:

func combineBits(int1: UInt8, int2: UInt8) -> UInt16 {
    return UInt16(int1) << 8 + UInt16(int2)
}

必须在移动/添加之前完成较大类型的转换

可能会溢出。

只是为了娱乐,替代方案是使用 Data

func combineBits(int1: UInt8, int2: UInt8) -> UInt16 {
    return Data([int2, int1]).withUnsafeBytes{ $0.pointee }
}

这是我要做的,以一种endian-correct的方式:

extension UInt16 {
    init(high: UInt8, low: UInt8) {
        self.init(littleEndian: UInt16(high) << 8 | UInt16(low))
    }
}
let i = UInt16(high: 0xAB, low: 0xCD)
// Represented on Little Endian platforms as 0xABCD
// Represented on    Big Endian platforms as 0xCDAB

这是一个更涉及的通用解决方案:

protocol PairedUnsignedInteger: UnsignedInteger {
    associatedtype SignedSelf: PairedSignedInteger
}
protocol PairedSignedInteger: SignedInteger {
    associatedtype UnsignedSelf: PairedUnsignedInteger
}

protocol BitPattternInitializable: FixedWidthInteger {
    associatedtype BitPatternSource: FixedWidthInteger
    init(bitPattern: BitPatternSource)
}
protocol UnsignedBitPattternInitializable: BitPattternInitializable, PairedSignedInteger
    where BitPatternSource == UnsignedSelf {}
protocol SignedBitPattternInitializable: BitPattternInitializable, PairedUnsignedInteger
    where BitPatternSource == SignedSelf {}
extension UInt:   PairedUnsignedInteger { typealias   SignedSelf =  Int   }
extension UInt8:  PairedUnsignedInteger { typealias   SignedSelf =  Int8  }
extension UInt16: PairedUnsignedInteger { typealias   SignedSelf =  Int16 }
extension UInt32: PairedUnsignedInteger { typealias   SignedSelf =  Int32 }
extension UInt64: PairedUnsignedInteger { typealias   SignedSelf =  Int64 }
extension  Int:     PairedSignedInteger { typealias UnsignedSelf = UInt   }
extension  Int8:    PairedSignedInteger { typealias UnsignedSelf = UInt8  }
extension  Int16:   PairedSignedInteger { typealias UnsignedSelf = UInt16 }
extension  Int32:   PairedSignedInteger { typealias UnsignedSelf = UInt32 }
extension  Int64:   PairedSignedInteger { typealias UnsignedSelf = UInt64 }
extension UInt:     SignedBitPattternInitializable {}
extension UInt8:    SignedBitPattternInitializable {}
extension UInt16:   SignedBitPattternInitializable {}
extension UInt32:   SignedBitPattternInitializable {}
extension UInt64:   SignedBitPattternInitializable {}
extension  Int:   UnsignedBitPattternInitializable {}
extension  Int8:  UnsignedBitPattternInitializable {}
extension  Int16: UnsignedBitPattternInitializable {}
extension  Int32: UnsignedBitPattternInitializable {}
extension  Int64: UnsignedBitPattternInitializable {}

protocol UnsignedHalfWidthInitializable: UnsignedInteger, FixedWidthInteger {
    associatedtype UnsignedHalfWidth: FixedWidthInteger
    init(high: UnsignedHalfWidth, low: UnsignedHalfWidth)
}
extension UnsignedHalfWidthInitializable {
    init(high: UnsignedHalfWidth, low: UnsignedHalfWidth) {
        self.init(littleEndian: Self(high) << UnsignedHalfWidth.bitWidth | Self(low))
    }
}
protocol SignedHalfWidthInitializable: UnsignedBitPattternInitializable {
    associatedtype UnsignedHalfWidth: UnsignedInteger, FixedWidthInteger
    init(high: UnsignedHalfWidth, low: UnsignedHalfWidth)
}
extension SignedHalfWidthInitializable {
    init(high: UnsignedHalfWidth, low: UnsignedHalfWidth) {
        let unsignedPromotedHigh = UnsignedSelf(high)
        let unsignedPromotedLow = UnsignedSelf(low)
        let unsignedLittleEndian = unsignedPromotedHigh << UnsignedHalfWidth.bitWidth | unsignedPromotedLow
        let signedLittleEndian = Self.init(bitPattern: unsignedLittleEndian)
        self.init(littleEndian: signedLittleEndian)
    }
}

extension UInt16: UnsignedHalfWidthInitializable { typealias UnsignedHalfWidth = UInt8  }
extension UInt32: UnsignedHalfWidthInitializable { typealias UnsignedHalfWidth = UInt16 }
extension UInt64: UnsignedHalfWidthInitializable { typealias UnsignedHalfWidth = UInt32 }
extension  Int16:   SignedHalfWidthInitializable { typealias UnsignedHalfWidth = UInt8  }
extension  Int32:   SignedHalfWidthInitializable { typealias UnsignedHalfWidth = UInt16 }
extension  Int64:   SignedHalfWidthInitializable { typealias UnsignedHalfWidth = UInt32 }

assert(UInt16(high: 0x12        as UInt8 ,  low: 0x34           as UInt8 ) == 0x1234                )
assert(UInt32(high: 0x1234      as UInt16,  low: 0x5678         as UInt16) == 0x1234_5678           )
assert(UInt64(high: 0x1234_5678 as UInt32,  low: 0x90AB_CDEF    as UInt32) == 0x1234_5678_90AB_CDEF )
assert( Int16(high: 0x12        as UInt8 ,  low: 0x34           as UInt8 ) == 0x1234                )
assert( Int32(high: 0x1234      as UInt16,  low: 0x5678         as UInt16) == 0x1234_5678           )
assert( Int64(high: 0x1234_5678 as UInt32,  low: 0x90AB_CDEF    as UInt32) == 0x1234_5678_90AB_CDEF )

最新更新