我在Golang中使用移位运算符<<
遇到了一个奇怪的问题。在我的最终代码中,移位值将是两个整数的绝对值。但是,Go包只为Abs
值定义float64
函数,因此我需要转换参数以使用它,然后将结果转换回uint
。
最后,此值将用作float64
参数,因此我将其转换回float64
。
问题是返回值的转换似乎不像我预期的那样工作......
var test float64
// all the following lines are working as expected
test = float64(1 << 10)
test = float64(1 << uint(10))
test = float64(1 << uint(float64(11-1)))
test = float64(1 << uint(-float64(1-11)))
// but this one does not: error at compilation
test = float64(1 << uint(math.Abs(10)))
我收到的错误是:
invalid operation: 1 << uint(math.Abs(10)) (shift of type float64)
然而,似乎只有施法操作才有效:
var test = uint(math.Abs(10))
fmt.Println(reflect.Kind(test))
// uint32
这是一个Golang问题吗?我没有在规格中找到的行为?我根本不理解的正常行为?
答案 0 :(得分:10)
来自spec:
shift表达式中的右操作数必须具有无符号整数类型,或者是可以转换为无符号整数类型的无类型常量。 如果非常量移位表达式的左操作数是无类型常量,则常量的类型是单独使用左操作数替换移位表达式时的类型。
所以float64(1 << uint(math.Abs(10)))
与float64(1) << uint(math.Abs(10))
基本相同,这会产生错误,因为不会简单地移动浮点数。
答案 1 :(得分:0)
你不应该使用math.Abs
。在To中,用一个小而简单的功能解决问题。例如,
package main
import "fmt"
func shift(a, b int) uint {
s := a - b
if s < 0 {
s = -s
}
return uint(s)
}
func main() {
a, b := 24, 42
i := 1 << shift(a, b)
fmt.Printf("%X\n", i)
f := float64(i)
fmt.Println(f, i)
}
输出:
40000
262144 262144