你如何在Swift中实现Java的无符号右移运算符?
根据Java's documentation,无符号右移运算符">>>"将零移动到最左边的位置,而在">>"之后的最左边的位置取决于符号扩展。
所以,例如,
long s1 = (-7L >>> 16); // result is 281474976710655L
long s2 = (-7L >> 16); // result is -1
为了在Swift中实现这一点,我会通过执行类似的操作来获取除符号位之外的所有位:
let lsb = Int64.max + negativeNumber + 1
请注意,该数字必须为负数!如果你溢出移位操作符,应用程序会崩溃EXC_BAD_INSTRUCTION,这不是很好...... 另外,我故意使用Int64。因为没有更大的数据类型,所以执行类似(1&lt;&lt; 63)的操作会溢出Int64并且也会崩溃。因此,不是在更大的数据类型中执行((1 <&lt;&lt;&lt; 63) - 1 + negativeNumber),而是将其写为Int64.max + negativeNumber - 1.
然后,用正常的逻辑移位移动该正数,并在符号后的第一个左位的符号中移位该位。
let shifted = (lsb >> bits) | 0x4000000000000000
然而,这并没有给我预期的结果,
((Int64.max - 7 + 1) >> 16) | 0x4000000000000000 // = 4611826755915743231
不确定我做错了什么...... 此外,是否可以将此运营商命名为&#39;&gt;&gt;&gt;&#39;并扩展Int64?
编辑: 在这里添加来自OOper的解决方案,
infix operator >>> : BitwiseShiftPrecedence
func >>> (lhs: Int64, rhs: Int64) -> Int64 {
return Int64(bitPattern: UInt64(bitPattern: lhs) >> UInt64(rhs))
}
我在Swift中实现了Java Random类,它还涉及将64位整数截断为32位。感谢OOper我刚才意识到我可以使用truncatingBitPattern初始化程序来避免溢出异常。功能&#39; next&#39;正如所描述的here在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)
}
答案 0 :(得分:6)
一种可靠的方法是使用无符号整数类型的无符号移位操作:
infix operator >>> : BitwiseShiftPrecedence
func >>> (lhs: Int64, rhs: Int64) -> Int64 {
return Int64(bitPattern: UInt64(bitPattern: lhs) >> UInt64(rhs))
}
print(-7 >>> 16) //->281474976710655
(使用-7
进行位计数16
测试似乎不是一个好例子,它会丢失16位右移的所有有效位。)
如果您想以自己的方式执行此操作,则按位ORed缺失符号位不能是常量0x4000000000000000
。当位计数== 0时,它需要为0x8000_0000_0000_0000(此常量在Swift Int64
中溢出),并且需要使用相同的位进行逻辑移位。
所以,你需要写这样的东西:
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
当您需要无符号移位操作时,使用无符号整数类型似乎要容易得多。
答案 1 :(得分:2)
Swift有无符号整数类型,因此不需要单独的无符号右移运算符。在决定不使用无符号类型之后,这是Java的一个选择。
答案 2 :(得分:0)
这个表达式对我有用:
((Int64.max - 7L + 1) >> 15)
无掩码,减少1位。
免责声明:无法在Swift中查看此内容。