具有可变位数的Swift符号扩展

时间:2018-04-01 05:29:22

标签: swift bit-manipulation

我需要将8位值符号扩展为12位。在C中,我可以这样做。我阅读了Apple的BinaryInteger协议文档,但它没有解释符号扩展到可变数量的位(我在Swift中也很新)。我怎么能在Swift中这样做,假设val是UInt8而numbits是12?

#define MASKBITS(numbits) ((1 << numbits) - 1)

#define SIGNEXTEND_TO_16(val, numbits)              \        
(                                                         \
(int16_t)((val & MASKBITS(numbits)) | (                 \
  (val & (1 << (numbits-1))) ? ~MASKBITS(numbits) : 0)  \
))

2 个答案:

答案 0 :(得分:2)

您可以使用Int8(bitPattern:)转换给定的无符号 具有相同二进制表示的有符号值的值, 然后通过转换为Int16进行符号扩展,再次进行无符号,最后进行截断 到给定的位数:

func signExtend(val: UInt8, numBits: Int) -> UInt16 {
    // Sign extend to unsigned 16-bit:
    var extended = UInt16(bitPattern: Int16(Int8(bitPattern: val)))
    // Truncate to given number of bits:
    if numBits < 16 {
        extended = extended & ((1 << numBits) - 1)
    }
    return extended
}

示例:

for i in 1...16 {
    let x = signExtend(val: 200, numBits: i)
    print(String(format: "%2d %04X", i, x))
}

输出:

 1 0000
 2 0000
 3 0000
 4 0008
 5 0008
 6 0008
 7 0048
 8 00C8
 9 01C8
10 03C8
11 07C8
12 0FC8
13 1FC8
14 3FC8
15 7FC8
16 FFC8

答案 1 :(得分:0)

在位流解析的上下文中,我有同样的问题。我需要将n位二进制补码值解析为Int32的代码。这是我的无条件解决方案:

jupyter notebook

以及显示如何使用该代码的单元测试功能:

extension UInt32 {
    func signExtension(n: Int) -> Int32 {
        let signed = Int32.init(bitPattern: self << (32 - n))
        let result = signed >> (32 - n)
        return result
    }
}