【问题标题】:Invalid operation: shift of type float64无效操作:float64 类型的移位
【发布时间】:2014-07-21 12:40:43
【问题描述】:

我在 Golang 中使用移位运算符 << 时遇到了一个奇怪的问题。在我的最终代码中,移位值将是两个整数的绝对值。但是,Go 包只为 float64 值定义了 Abs 函数,所以我需要转换参数才能使用它,然后将结果转换回 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)

但是,似乎单独的 cast 操作有效:

var test = uint(math.Abs(10))
fmt.Println(reflect.Kind(test))
// uint32

这是一个 Golang 问题吗?我在规范中没有找到的行为?我根本不明白的正常行为?

这里是游乐场:http://play.golang.org/p/36a8r8CCYL

【问题讨论】:

    标签: go bit-shift


    【解决方案1】:

    来自spec

    移位表达式中的右操作数必须是无符号整数类型或者是可以转换为无符号整数类型的无类型常量。 如果非常量移位表达式的左操作数是无类型常量,则该常量的类型就是移位表达式仅被其左操作数替换时的类型。

    所以float64(1 &lt;&lt; uint(math.Abs(10)))float64(1) &lt;&lt; uint(math.Abs(10)) 基本相同,这会产生错误,因为不会简单地移动浮点数。

    【讨论】:

    • 首先,reflect.Kind(1) 是类型转换,而不是函数调用。你需要的是reflect.ValueOf(1).Kind(),它给出了int。其次,float64(1 &lt;&lt; uint(float64(10))) 之所以有效,是因为它是一个常数,而不是一个变量。规范引用是关于 非常量 移位表达式。
    • @julienc 文字1 是一个无类型常量。引用的规范 Ainar-G 的部分解释了编译器如何精确定位无类型常量的类型。 reflect 所说的无类型常量的类型取决于上下文。
    【解决方案2】:

    您不应该使用math.Abs。在 Go 中,用一个小而简单的函数来解决问题。例如,

    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
    

    【讨论】:

    • 你不使用math.Abs 可能是对的,但现在我仍然想知道我得到错误的原因:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-07
    • 2013-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多