Swift和Javascript不同的按位计算结果
我正在尝试将Javascript哈希函数移植到Swift: 在Javascript中: 68207947269^51=-511529418 其中与Swift 5中的计算相同 68207947269^51=68207947318 如何,为什么它们不同 编辑,添加了JS哈希函数Swift和Javascript不同的按位计算结果,javascript,swift,hash,bitwise-operators,Javascript,Swift,Hash,Bitwise Operators,我正在尝试将Javascript哈希函数移植到Swift: 在Javascript中: 68207947269^51=-511529418 其中与Swift 5中的计算相同 68207947269^51=68207947318 如何,为什么它们不同 编辑,添加了JS哈希函数 function hash(str) { var hash = 5381, i = str.length; while(i) { hash = (hash * 33) ^ str.char
function hash(str) {
var hash = 5381,
i = str.length;
while(i) {
hash = (hash * 33) ^ str.charCodeAt(--i);
}
/* JavaScript does bitwise operations (like XOR, above) on 32-bit signed
* integers. Since we want the results to be always positive, convert the
* signed int to an unsigned by doing an unsigned bitshift. */
return hash >>> 0;
}
编辑2,添加当前断开的Swift:
extension String {
subscript(i: Int) -> String {
return String(self[index(startIndex, offsetBy: i)])
}
}
extension Character {
func unicodeScalarCodePoint() -> UInt32 {
let characterString = String(self)
let scalars = characterString.unicodeScalars
return scalars[scalars.startIndex].value
}
}
func hashString(_ string: String) -> UInt32 {
var hash: Int32 = 5381
var i = string.count - 1
while(i >= 0) {
let char = Int32(Character(string[i]).unicodeScalarCodePoint())
// Crash here with error: `Swift runtime failure: arithmetic overflow`
let hashMultiply = Int32(truncating: NSNumber(value: hash * 33))
hash = hashMultiply ^ char
i -= 1
}
return UInt32(bitPattern: hash)
}
hashString("0x8f1083db77b5F556E46Ac46A29DE86e01031Bb14")
请注意:
操作数转换为32位整数,并由一系列位0和1表示。超过32位的数字将丢弃其最高有效位
Swift中的整数文本默认为Int类型,这是您的体系结构的字宽。如果你在最近的苹果设备上试用,它将是64位的
因此,要模拟JavaScript行为,您需要强制转换为Int32:
Int32(truncatingIfNeeded: 68207947269) ^ Int32(51)
这将给出所需的结果-511529418
请注意,JavaScript代码丢弃整数68207947269的位,因为它不能表示为32位整数。请注意:
操作数转换为32位整数,并由一系列位0和1表示。超过32位的数字将丢弃其最高有效位
Swift中的整数文本默认为Int类型,这是您的体系结构的字宽。如果你在最近的苹果设备上试用,它将是64位的
因此,要模拟JavaScript行为,您需要强制转换为Int32:
Int32(truncatingIfNeeded: 68207947269) ^ Int32(51)
这将给出所需的结果-511529418
请注意,JavaScript代码丢弃整数68207947269的位,因为它不能表示为32位整数。根据,JavaScript中的按位运算符使用32位操作数。68207947269太大,无法用32位表示,因此它首先自动被截断,然后执行逐位操作
默认情况下,Swift整数文本的类型为Int,Int的大小取决于平台。它很可能是64位,这就是为什么会产生不同的结果
要生成与JavaScript代码相同的结果,请先截断它,将其转换为Int32:
Int32(truncatingIfNeeded: 68207947269) ^ 51
请注意,结果是得到一个Int32。以后可能需要进行更多类型转换
关于你的快速翻译,我发现两个主要问题
首先,散列*33将溢出并导致崩溃。JavaScript版本不需要担心这一点,因为结果将简单地用JavaScript包装。幸运的是,如果结果溢出,而不是在Swift中崩溃,也会有一个解决方案。因此,您可以:
hash &* 33
其次,处理字符串的方式与JavaScript版本不同。在JavaScript中,返回一个UTF-16代码单元,但Swift代码取而代之的是unicode标量
要获得相同的行为,您应该执行以下操作:
extension String.UTF16View {
subscript(i: Int) -> Element {
return self[index(startIndex, offsetBy: i)]
}
}
...
Int32(string.utf16[i])
根据,JavaScript中的位运算符使用32位操作数。68207947269太大,无法用32位表示,因此它首先自动被截断,然后执行逐位操作
默认情况下,Swift整数文本的类型为Int,Int的大小取决于平台。它很可能是64位,这就是为什么会产生不同的结果
要生成与JavaScript代码相同的结果,请先截断它,将其转换为Int32:
Int32(truncatingIfNeeded: 68207947269) ^ 51
请注意,结果是得到一个Int32。以后可能需要进行更多类型转换
关于你的快速翻译,我发现两个主要问题
首先,散列*33将溢出并导致崩溃。JavaScript版本不需要担心这一点,因为结果将简单地用JavaScript包装。幸运的是,如果结果溢出,而不是在Swift中崩溃,也会有一个解决方案。因此,您可以:
hash &* 33
其次,处理字符串的方式与JavaScript版本不同。在JavaScript中,返回一个UTF-16代码单元,但Swift代码取而代之的是unicode标量
要获得相同的行为,您应该执行以下操作:
extension String.UTF16View {
subscript(i: Int) -> Element {
return self[index(startIndex, offsetBy: i)]
}
}
...
Int32(string.utf16[i])
您在Swift中使用的是什么类型?或者你只是将其作为一个表达式输入?我知道Javascript在Int32s中用于it计算,我尝试过,但没有成功-老实说,我不介意输入什么类型use@idmean我加上了电流。它仍然与INT32TRUNCATINGIFREADED:updateOn保持平衡,该错误发生在哪一行?如果你把你的计算分成几行,这肯定会有助于调试。你为什么要做NSNumbervalue:hash*33?你在Swift中使用的是什么类型?或者你只是将其作为一个表达式输入?我知道Javascript在Int32s中用于it计算,我尝试过,但没有成功-老实说,我不介意输入什么类型use@idmean我加上了电流。它仍然与INT32TRUNCATINGIFREADED:updateOn保持平衡,该错误发生在哪一行?如果你把计算分成几行,这肯定会有助于调试。你为什么要做NSNumbervalue:hash*33?