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)
一种可靠的方法是使用无符号整数类型的无符号移位操作:
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)
当您需要无符号移位操作时,使用无符号整数类型似乎要容易得多.
| 归档时间: |
|
| 查看次数: |
2358 次 |
| 最近记录: |