Swift中的无符号右移运算符'>>>'

end*_*vid 3 bit-manipulation swift

你如何在Swift中实现Java的无符号右移运算符?

根据Java的文档,无符号右移运算符">>>"将零移动到最左边的位置,而">>"之后的最左边位置取决于符号扩展.

所以,例如,

    long s1 = (-7L >>> 16); // result is 281474976710655L
    long s2 = (-7L >> 16); // result is -1
Run Code Online (Sandbox Code Playgroud)

为了在Swift中实现这一点,我会通过执行类似的操作来获取除符号位之外的所有位.

    let lsb = Int64.max + negativeNumber + 1
Run Code Online (Sandbox Code Playgroud)

请注意,该数字必须为负数!如果你溢出移位操作符,应用程序崩溃与EXC_BAD_INSTRUCTION,这不是很好......而且,我故意使用Int64.因为没有更大的数据类型,所以执行类似(1 << 63)的操作会溢出Int64并且也会崩溃.因此,我没有在更大的数据类型中执行((1 << 63) - 1 + negativeNumber),而是将其写为Int64.max + negativeNumber - 1.

然后,将该正数与正常逻辑移位相移,并将该符号从符号后第一个左位中的符号移位.

    let shifted = (lsb >> bits) | 0x4000000000000000
Run Code Online (Sandbox Code Playgroud)

但是,这并没有给我预期的结果,

    ((Int64.max - 7 + 1) >> 16) | 0x4000000000000000 // = 4611826755915743231
Run Code Online (Sandbox Code Playgroud)

不确定我做错了什么...另外,是否可以将此运算符命名为">>>"并扩展Int64?

编辑:在这里添加来自OOper的解决方案,

infix operator >>> : BitwiseShiftPrecedence

func >>> (lhs: Int64, rhs: Int64) -> Int64 {
  return Int64(bitPattern: UInt64(bitPattern: lhs) >> UInt64(rhs))
}
Run Code Online (Sandbox Code Playgroud)

我在Swift中实现了Java Random类,它还涉及将64位整数截断为32位.感谢OOper我刚才意识到我可以使用truncatingBitPattern初始化程序来避免溢出异常.这里描述的函数'next' 在Swift中变成了这个,

var seed: Int64 = 0
private func next(_ bits: Int32) -> Int32 {
    seed = (seed &* 0x5DEECE66D &+ 0xB) & ((1 << 48) - 1)
    let shifted : Int64 = seed >>> (48 - Int64(bits))
    return Int32(truncatingBitPattern: shifted)
}
Run Code Online (Sandbox Code Playgroud)

OOP*_*Per 6

一种可靠的方法是使用无符号整数类型的无符号移位操作:

infix operator >>> : BitwiseShiftPrecedence

func >>> (lhs: Int64, rhs: Int64) -> Int64 {
    return Int64(bitPattern: UInt64(bitPattern: lhs) >> UInt64(rhs))
}

print(-7 >>> 16) //->281474976710655
Run Code Online (Sandbox Code Playgroud)

(-7用于测试位数16似乎不是一个很好的例子,它会丢失16位右移的所有有效位.)

如果您想以您的方式执行此操作,则按位ORed丢失符号位不能是常量0x4000000000000000.Int64当位计数== 0时,它需要为0x8000_0000_0000_0000(此常量在Swift中溢出),并且需要使用相同的位进行逻辑移位.

所以,你需要写这样的东西:

infix operator >>>> : BitwiseShiftPrecedence

func >>>> (lhs: Int64, rhs: Int64) -> Int64 {
    if lhs >= 0 {
        return lhs >> rhs
    } else {
        return (Int64.max + lhs + 1) >> rhs | (1 << (63-rhs))
    }
}

print(-7 >>>> 16) //->281474976710655
Run Code Online (Sandbox Code Playgroud)

当您需要无符号移位操作时,使用无符号整数类型似乎要容易得多.