Golang模拟JavaScript中的左右移位运算符实现
Golang模拟JavaScript中的左右移位运算符实现 我需要实现与JavaScript中相同的位移运算结果。该如何实现?
目前在JavaScript中:
console.log(20192019 << 10); // -798209024
console.log(201920192019 >> 2) // 14182276
目前在Go中:
fmt.Println(20192019 << 10) // 20676627456
fmt.Println(201920192019 >> 2) // 50480048004
我希望在Go中实现:
fmt.Println(20192019 << 10) // -798209024
fmt.Println(201920192019 >> 2) // 14182276
谢谢!
更多关于Golang模拟JavaScript中的左右移位运算符实现的实战教程也可以访问 https://www.itying.com/category-94-b0.html
现在我想知道为什么将其包装在函数中会改变行为?
更多关于Golang模拟JavaScript中的左右移位运算符实现的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我的输出:
20676627456
50480048004
[@enzovitaliy] 这个方案对你有用吗:https://play.golang.org/p/3caJWUs5IjG
我理解,但是是否有可能从64位数模拟出32位数?我尝试用不同的系数减去32位数,有时候能成功,但只针对特定值。
你所说的"有时候"是什么意思?
如果你需要64位精度,那就坚持使用它;如果你需要32位精度,那就不要使用64位。
// 代码示例保留原样
使用 int64 就不会出现 int32 的溢出行为,这正是我之前说"附注:强制使用 int32 可能已经足够,不过 201920192019 这个值已经会导致溢出……"时想要表达的意思。
这是因为当你使用常量并对常量进行位移操作时,编译器会将它们折叠成常量,并且知道它们超出了范围。通过将int64到int32的转换放入函数中,溢出会被推迟到运行时,而在运行时溢出是不被检查的。
NobbZ:
你所说的"有时候"是什么意思?
它对特定值有效,但如果我改变这个值,就不再起作用了。 类似 1 << 32, (1 << 32) * 5 这样的情况(这些是我前面提到的系数)。
是的,你之前已经提到过,但能否请你分享产生该输出的确切代码?将你上面的代码片段放入 playground 的 main 函数中会产生所引用的编译错误。
NobbZ:
是的,您已经提到过这一点,但能否请您分享产生该输出的确切代码?将您上面的代码片段放入 Playground 的
main函数中会产生所引用的编译错误。
在 Playground 上,您需要显式将类型转换为 int64:
package main
import (
"fmt"
)
func main() {
fmt.Println(int64(20192019) << 10)
fmt.Println(int64(201920192019) >> 2)
}
引用 enzovitaliy:
fmt.Println(20192019 << 10) // -798209024 fmt.Println(201920192019 >> 2) // 14182276
嗯,我实际看到的是:
./prog.go:8:23: constant 20676627456 overflows int
./prog.go:9:27: constant 50480048004 overflows int
那么你能否展示一下实际产生你所见结果的代码呢?
PS:强制使用 int32 可能就足够了,不过 201920192019 在这种情况下已经溢出了……
在Go中实现与JavaScript相同的位移运算结果,关键在于处理整数溢出和符号扩展的差异。JavaScript使用32位有符号整数进行位移运算,而Go会根据操作数类型自动选择位数。
以下是解决方案:
package main
import "fmt"
// 模拟JavaScript的32位左移运算
func jsLeftShift(x int32, n uint) int32 {
return x << n
}
// 模拟JavaScript的32位右移运算
func jsRightShift(x int32, n uint) int32 {
return x >> n
}
// 处理大整数的辅助函数
func toInt32(x int64) int32 {
return int32(x)
}
func main() {
// 示例1: 20192019 << 10
result1 := jsLeftShift(toInt32(20192019), 10)
fmt.Println(result1) // -798209024
// 示例2: 201920192019 >> 2
result2 := jsRightShift(toInt32(201920192019), 2)
fmt.Println(result2) // 14182276
}
更简洁的写法:
package main
import "fmt"
func main() {
// 直接转换为int32进行位移运算
fmt.Println(int32(20192019) << 10) // -798209024
fmt.Println(int32(201920192019) >> 2) // 14182276
}
对于通用的JavaScript位移运算模拟:
package main
import "fmt"
// 模拟JavaScript的<<运算符
func jsLeftShift(val interface{}, shift uint) int32 {
switch v := val.(type) {
case int:
return int32(v) << shift
case int32:
return v << shift
case int64:
return int32(v) << shift
default:
return 0
}
}
// 模拟JavaScript的>>运算符
func jsRightShift(val interface{}, shift uint) int32 {
switch v := val.(type) {
case int:
return int32(v) >> shift
case int32:
return v >> shift
case int64:
return int32(v) >> shift
default:
return 0
}
}
func main() {
fmt.Println(jsLeftShift(20192019, 10)) // -798209024
fmt.Println(jsRightShift(201920192019, 2)) // 14182276
}
关键点:
- JavaScript位移运算基于32位有符号整数
- 在Go中需要明确转换为int32类型
- 溢出时会产生与JavaScript相同的结果
- 右移运算会保持符号位(算术右移)

