无效操作:float64 类型的移位操作。

huangapple go评论83阅读模式
英文:

Invalid operation: shift of type float64

问题

我在使用Golang中的位移运算符<<时遇到了一个奇怪的问题。在我的最终代码中,位移值将是两个整数的绝对值。然而,Go语言包只为float64类型定义了Abs函数,所以我需要将参数转换为float64类型来使用它,然后再将结果转换回uint类型。

最后,这个值将被用作float64类型的参数,所以我在此之后将其转换回float64类型。

问题是返回值的转换似乎不像我预期的那样工作...

var test float64

// 以下所有行都按预期工作
test = float64(1 << 10)
test = float64(1 << uint(10))
test = float64(1 << uint(float64(11-1)))
test = float64(1 << uint(-float64(1-11)))

// 但是这一行不工作:编译时出错
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

这是一个示例:http://play.golang.org/p/36a8r8CCYL

英文:

I'm facing a strange issue using the shift operator &lt;&lt; in Golang. In my final code, the shift value will be the absolute value of two integers. However, the Go package only defines the Abs function for float64 values, so I will need to cast the parameters to use it, and then cast the result back to uint.

Finally, this value will be used as a float64 parameter, so I cast it back to float64 after that.

The problem is that the return value's cast does not seem to work as I expected...

var test float64

// all the following lines are working as expected
test = float64(1 &lt;&lt; 10)
test = float64(1 &lt;&lt; uint(10))
test = float64(1 &lt;&lt; uint(float64(11-1)))
test = float64(1 &lt;&lt; uint(-float64(1-11)))

// but this one does not: error at compilation
test = float64(1 &lt;&lt; uint(math.Abs(10)))

The error I'm receiving is:

invalid operation: 1 &lt;&lt; uint(math.Abs(10)) (shift of type float64)

However, it seems that the cast operation alone works:

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

Is it a Golang issue ? A behaviour I did not find in the specifications ? A normal behaviour I simply don't understand ?

Here is a playground: http://play.golang.org/p/36a8r8CCYL

答案1

得分: 13

根据规范

移位表达式中的右操作数必须具有无符号整数类型,或者是可以转换为无符号整数类型的无类型常量。如果非常量移位表达式的左操作数是无类型常量,则该常量的类型将与仅使用左操作数的移位表达式的类型相同。

因此,float64(1 << uint(math.Abs(10)))基本上与float64(1) << uint(math.Abs(10))是相同的,但会产生错误,因为不能简单地将浮点数进行移位操作。

英文:

From the spec:

>The right operand in a shift expression must have unsigned integer type or be an untyped constant that can be converted to unsigned integer type. If the left operand of a non-constant shift expression is an untyped constant, the type of the constant is what it would be if the shift expression were replaced by its left operand alone.

So float64(1 &lt;&lt; uint(math.Abs(10))) is basically the same as float64(1) &lt;&lt; uint(math.Abs(10)), which produces an error, since one does not simply shift a float.

答案2

得分: 0

你不应该使用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
英文:

You shouldn't be using math.Abs. In Go, solve the problem with a small, simple function. For example,

package main

import &quot;fmt&quot;

func shift(a, b int) uint {
	s := a - b
	if s &lt; 0 {
		s = -s
	}
	return uint(s)
}

func main() {
	a, b := 24, 42
	i := 1 &lt;&lt; shift(a, b)
	fmt.Printf(&quot;%X\n&quot;, i)
	f := float64(i)
	fmt.Println(f, i)
}

Output:

40000
262144 262144

huangapple
  • 本文由 发表于 2014年7月21日 20:40:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/24865339.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定