如何在移位整数时绕过Go int64值的限制?

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

How to bypass Go int64 value limits while shifting integers?

问题

我正在尝试使用Go语言获取KiB、MiB、...、ZiB、Yib的值,它们分别对应KibiByte、MebiByte、...、ZebiByte、YobiByte

我的Golang代码如下:

package main
import (
	"fmt"
)

func main() {
    s := []string{"KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"}

    for k,v := range(s) {
		fmt.Printf("%s: %v\n", v, 1 << uint64(10 * (k+1)))
	}
}

但是,ZiB和YiB的值超出了Go的uint64范围,这就是为什么我得到以下输出的原因:

KiB: 1024
MiB: 1048576
GiB: 1073741824
TiB: 1099511627776         // 超过了1 << 32
PiB: 1125899906842624
EiB: 1152921504606846976
ZiB: 0                    // 超过了1 << 64
YiB: 0                    // 超过了1 << 64

另外,使用相同的位移逻辑在Python3中,可以得到以下正确的输出:

a = ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"]
for k,v in enumerate(a):
    print("{}: {}".format(v, 1 << (10 *(k+1))))

输出结果如下:

KiB: 1024
MiB: 1048576
GiB: 1073741824
TiB: 1099511627776
PiB: 1125899906842624
EiB: 1152921504606846976
ZiB: 1180591620717411303424
YiB: 1208925819614629174706176

所以,我应该如何绕过Go的uint64限制,使用位移整数来获取正确的值,就像在Python中使用位移整数一样。

谢谢。

英文:

I'm trying with Go to get values of KiB, MiB, ..., ZiB, Yib which are respectively KibiByte, MebiByte, ..., ZebiByte, YobiByte.

My code in Golang is:

package main 
import ( 
	&quot;fmt&quot;
)

func main() {
    s := []string{&quot;KiB&quot;, &quot;MiB&quot;, &quot;GiB&quot;, &quot;TiB&quot;, &quot;PiB&quot;, &quot;EiB&quot;, &quot;ZiB&quot;, &quot;YiB&quot;}

    for k,v := range(s) {
		fmt.Printf(&quot;%s: %v\n&quot;, v, 1 &lt;&lt; uint64(10 * (k+1)))
	}
}

But, the values of ZiB and YiB overflows Go uint64 and this why I'm having this output:

KiB: 1024
MiB: 1048576
GiB: 1073741824
TiB: 1099511627776         // exceeds 1 &lt;&lt; 32
PiB: 1125899906842624
EiB: 1152921504606846976
ZiB: 0                    // exceeds 1 &lt;&lt; 64
YiB: 0                    // exceeds 1 &lt;&lt; 64

Otherwise, with the same shifting logic in Python3 within this code:

a = [&quot;KiB&quot;, &quot;MiB&quot;, &quot;GiB&quot;, &quot;TiB&quot;, &quot;PiB&quot;, &quot;EiB&quot;, &quot;ZiB&quot;, &quot;YiB&quot;]
for k,v in enumerate(a):
    print(&quot;{}: {}&quot;.format(v, 1 &lt;&lt; (10 *(k+1))))

The output is correct, like the output below:

KiB: 1024
MiB: 1048576
GiB: 1073741824
TiB: 1099511627776
PiB: 1125899906842624
EiB: 1152921504606846976
ZiB: 1180591620717411303424
YiB: 1208925819614629174706176

So, how can I bypass Go uint64 limits and get the correct values using shifting integers like what I can get from shifting integers using Python.

Thanks.

答案1

得分: 9

你不能使用原始的uint64来处理需要超过64位的数字。Python具有任意精度整数,要在Go中实现相同的功能,你需要使用math/big包。

s := []string{"KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"}

one := big.NewInt(1)
for k, v := range s {
    fmt.Printf("%s: %v\n", v, new(big.Int).Lsh(one, uint(10*(k+1))))
}

链接:https://play.golang.org/p/i5v5P5QgQb

英文:

You can't work with numbers that require more than 64bits with a primitive uint64. Python has arbitrary precision integers, and to get the same in Go you need to use the math/big package.

s := []string{&quot;KiB&quot;, &quot;MiB&quot;, &quot;GiB&quot;, &quot;TiB&quot;, &quot;PiB&quot;, &quot;EiB&quot;, &quot;ZiB&quot;, &quot;YiB&quot;}

one := big.NewInt(1)
for k, v := range s {
	fmt.Printf(&quot;%s: %v\n&quot;, v, new(big.Int).Lsh(one, uint(10*(k+1))))
}

https://play.golang.org/p/i5v5P5QgQb

huangapple
  • 本文由 发表于 2017年2月10日 02:25:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/42144234.html
匿名

发表评论

匿名网友

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

确定