【问题标题】:Max value on 64 bit64位最大值
【发布时间】:2020-04-08 05:18:04
【问题描述】:

以下代码编译:

package main

import "fmt"

const (
    // Max integer value on 64 bit architecture.
    maxInt = 9223372036854775807

    // Much larger value than int64.
    bigger = 9223372036854775808543522345

    // Will NOT compile
    // biggerInt int64 = 9223372036854775808543522345
)

func main() {
    fmt.Println("Will Compile")
    //fmt.Println(bigger) // error
}

类型是 内存中的大小 + 该内存中的位表示

编译时分配给bigger 的隐式类型是什么?因为fmt.Println(bigger) 行的错误constant 9223372036854775808543522345 overflows int

【问题讨论】:

  • 没什么。这是一个无类型的常量。将类型分配给变量时将选择它。 See The Go Blog: Constants。查看相关问题:How does Go perform arithmetic on constants?What is the purpose of arbitrary precision constants in Go?
  • @icza fmt.Println(bigger) 给出错误constant 9223372036854775808543522345 overflows int
  • @overexchange: sure: fmt.Println(bigger) 尝试将无类型常量分配给一个变量——一个 未命名 变量,但类型为 int,然后可以传递到fmt.Println。不合适,你会收到投诉。
  • @torek go run myfile.go 编译并执行机器代码以给出此错误。如何只编译这个文件myfile.gomyfile.o
  • 编译。它无法编译。它不执行。 编译器 打印错误。 go run 仅在程序编译后运行。

标签: go


【解决方案1】:

那些是无类型的常量。它们比类型常量有更大的限制:

https://golang.org/ref/spec#Constants

特别是:

用至少 256 位表示整数常量。

【讨论】:

  • 是的.. 但是如果不能将这些较大的值分配给变量,我该如何在程序中使用这些较大的限制?
  • 您可以使用它们来定义可以分配给变量的其他无类型常量。
  • 当 GoLang 编译器在程序中不可用时,允许 256 位整数值和 256 位浮点精度的意义何在?
  • 只有语言设计师才能回答这个问题。但我认为重点是防止在不断计算期间发生溢出。您可能会遇到可以使用非常大的中间常数结果来获得可用常数值的情况。你可以在你的程序中定义一个常量bigger/maxInt,然后使用它。
【解决方案2】:

没有,它是一个无类型的常量。因为您还没有将它分配给任何变量或在任何表达式中使用它,所以它还没有“需要”被赋予任何具体类型的表示。 Go 中的数字常量实际上具有无限精度(语言规范要求整数至少为 256 位,浮点数至少为 256 尾数,但我相信golang/go 编译器使用 Go 任意精度内部类型仅受内存限制)。见the section about Constants in the language spec

如果不能将常量分配给任何类型的变量,它还有什么用?好吧,它可以是constant expression 的一部分。常量表达式以任意精度计算,它们的结果可能可以赋值给一个变量。换句话说,只要所有计算发生在编译时,就可以使用太大而无法表示的值来获得可表示的答案。

【讨论】:

  • 如何编译这段代码,因为go run myfile.go在注释代码fmt.Println(bigger)后执行良好?
  • @overexchange 有什么问题?
  • 注释行fmt.Println(bigger)成功编译代码(go tool compile myfile.go)。但取消注释该行失败,为什么?
  • @overexchange 因为值太大而无法转换为 int。
【解决方案3】:

来自this comment

我的目标是将更大的 = 9223372036854775808543522345 转换为二进制形式

我们发现您的问题是XY problem

由于我们确实知道该常数超过 64 位,因此我们需要将其拆分为多个 64 位字,或者将其存储在某种更大的整数存储中。

Go 为通用大数运算提供了math/big,或者在这种情况下,我们可以利用这样一个事实,即在 @ 中存储多达 127 位有符号值(或 128 位无符号值)很容易987654326@ 持有两个 64 位整数(至少其中一个是无符号的)。

This rather trivial program 打印转换为二进制的结果:

500000000 x 2-sup-64 + 543522345 as binary:
111011100110101100101000000000000000000000000000000000000000000100000011001010111111000101001
package main

import "fmt"

const (
    // Much larger value than int64.
    bigger = 9223372036854775808543522345
    d64    = 1 << 64
)

type i128 struct {
    Upper int64
    Lower uint64
}

func main() {
    x := i128{Upper: bigger / d64, Lower: bigger % d64}
    fmt.Printf("%d x 2-sup-64 + %d as binary:\n%b%.64b\n", x.Upper, x.Lower, x.Upper, x.Lower)
}

【讨论】:

  • 这是(10000000000000000000000000000000000000000000000000000000000000000d64 的二进制表示吗?这是 65 位大小
  • 如果是 1 后跟 64 个零,那么是的。 2-sup-k(对于非负整数 k)总是一个位,当表示为二进制数时,是一个 1 后跟 k 个零。
猜你喜欢
  • 2011-01-06
  • 2011-01-28
  • 2020-03-29
  • 1970-01-01
  • 2011-07-12
  • 1970-01-01
  • 2013-02-12
  • 1970-01-01
  • 2010-10-24
相关资源
最近更新 更多