我目前正在做 Go Lang 教程,准确地说是“数值常量”。示例代码以以下语句开头:
const (
// Create a huge number by shifting a 1 bit left 100 places.
// In other words, the binary number that is 1 followed by 100 zeroes.
Big = 1 << 100
// Shift it right again 99 places, so we end up with 1<<1, or 2.
Small = Big >> 99
)
Run Code Online (Sandbox Code Playgroud)
常量Big显然很大,我正在尝试打印它及其类型,如下所示:
fmt.Printf("%T", Big)
fmt.Println(Big)
Run Code Online (Sandbox Code Playgroud)
但是,我对这两行都收到以下错误:
# 命令行参数 ./compile26.go:19: 常量 1267650600228229401496703205376 溢出 int
我会尝试将 Big 转换为其他类型,例如uint64,它溢出了相同的错误,或者只是将其转换为字符串,但是在尝试时Big.String()出现以下错误: …
只要使用浮点数,0.1就不能在内存中精确表示,所以我们知道这个值通常是0.10000000000000004.
但是当使用go时加0.1和0.2.我得到0.3.
fmt.Println(0.1 + 0.2)
// Output : 0.3
Run Code Online (Sandbox Code Playgroud)
为什么0.3出来而不是0.30000000000000004?
我正在看看A Tour of Go,我对它们的基本类型感到困惑.示例:
MaxInt uint64 = 1<<64 - 1
Run Code Online (Sandbox Code Playgroud)
不应该在无符号的64位整数中向左移动1 64个位置导致溢出(也就是稍微移过MSB一点)?
但是,在将行更改为以下内容之前,编译器不会抱怨:
MaxInt uint64 = 1<<65 - 1
./basic-types.go:5: constant 36893488147419103231 overflows uint64
Run Code Online (Sandbox Code Playgroud)
如果我编写一些代码来迭代不同长度的左移,包括按照上面的例子中的65移动导致编译器barf,我看到两件事:
它的行为与我预期的一样,因为1<<63在MSB中1可能是uint64
它不再溢出(嗯?!?!)
码:
package main
import "fmt"
func main() {
for i := 60; i < 66; i++ {
var j uint64 = 1 << uint64(i) - 1
fmt.Printf("%2d | %64b | %#18x\n", i, j, j)
}
Run Code Online (Sandbox Code Playgroud)
输出:
60 | 111111111111111111111111111111111111111111111111111111111111 | 0xfffffffffffffff
61 | 1111111111111111111111111111111111111111111111111111111111111 | 0x1fffffffffffffff
62 | 11111111111111111111111111111111111111111111111111111111111111 …Run Code Online (Sandbox Code Playgroud) 为什么下面的代码无法编译?
package main
import (
"fmt"
"unsafe"
)
var x int = 1
const (
ONE int = 1
MIN_INT int = ONE << (unsafe.Sizeof(x)*8 - 1)
)
func main() {
fmt.Println(MIN_INT)
}
Run Code Online (Sandbox Code Playgroud)
我收到一个错误
main.go:12:常量2147483648溢出int
以上陈述是正确的.是的,2147483648溢出int(在32位架构中).但是班次操作应该导致负值,即-2147483648.
但相同的代码工作,如果我将常量更改为变量,我得到预期的输出.
package main
import (
"fmt"
"unsafe"
)
var x int = 1
var (
ONE int = 1
MIN_INT int = ONE << (unsafe.Sizeof(x)*8 - 1)
)
func main() {
fmt.Println(MIN_INT)
}
Run Code Online (Sandbox Code Playgroud) 我正在学习使用官方旅游/教程的golang.在其中一个例子中,我看到一个说明An untyped constant takes the type needed by its context.
我正在尝试这个:
package main
import "fmt"
const (
// Create a huge number by shifting a 1 bit left 100 places.
// In other words, the binary number that is 1 followed by 100 zeroes.
Big = 1 << 100
)
func main() {
fmt.Printf("Big is of type %T\n", Big)
}
Run Code Online (Sandbox Code Playgroud)
但是当我运行它时失败了:
# command-line-arguments
./compile63.go:12:13: constant 1267650600228229401496703205376 overflows int
Run Code Online (Sandbox Code Playgroud)
为什么我无法通过这种方式发现常数的类型?(请注意我是一个完全的菜鸟,很可能还没有发现足够的语言能够自己解决这个问题).
我不能在golang如何理解1<<s返回0如果var s uint = 33。但是1<<33返回8589934592。移位运算符转换如何以0值结束。
我正在阅读语言规范,并停留在本节中:https : //golang.org/ref/spec#Operators
特别是来自文档的这一段:
“移位表达式中的右操作数必须具有无符号整数类型,或者是可由uint类型的值表示的无类型常量。 如果非恒定移位表达式的左操作数是无类型常量,则首先将其隐式转换为该类型它会假设是否仅将shift表达式替换为其左操作数。”
来自Golang官方文档的一些示例:
var s uint = 33
var i = 1<<s // 1 has type int
var j int32 = 1<<s // 1 has type int32; j == 0
var k = uint64(1<<s) // 1 has type uint64; k == 1<<33
Run Code Online (Sandbox Code Playgroud)
更新:
另一个非常相关的问题,例如:
package main
import (
"fmt"
)
func main() {
v := int16(4336)
fmt.Println(int8(v))
}
Run Code Online (Sandbox Code Playgroud)
该程序返回 …
有人能告诉我为什么这样有效:
s := time.Hour/73.0
fmt.Println("sleeping: ", s)
time.Sleep(s)
Run Code Online (Sandbox Code Playgroud)
但这失败了:
d := 73.0
s := time.Hour/d
fmt.Println("sleeping: ", s)
time.Sleep(s)
Run Code Online (Sandbox Code Playgroud)
这是错误:
invalid operation: time.Hour / d (mismatched types time.Duration and float64)
Run Code Online (Sandbox Code Playgroud) Go具有任意大小和精度的无类型精确数字常量。该规范要求所有编译器支持至少256位的整数,并且至少浮动272位(尾数为256位,指数为16位)。因此,要求编译器忠实准确地表示如下表达式:
const (
PI = 3.1415926535897932384626433832795028841971
Prime256 = 84028154888444252871881479176271707868370175636848156449781508641811196133203
)
Run Code Online (Sandbox Code Playgroud)
这很有趣......,但我无法找到任何方式实际使用任何这种持续超过64位的具体类型的最大精度int64,uint64,float64,complex128(这只是一对float64值)。即使是标准库中的大数字类型 big.Int,big.Float也无法从大数字常量中进行初始化-必须从字符串常量或其他表达式中反序列化它们。
基本机制很明显:这些常量仅在编译时存在,并且必须强制为某个可在运行时表示的值才能在运行时使用。它们是仅在代码中和编译期间存在的语言构造。您无法在运行时检索常量的原始值;它不存储在已编译程序本身的某个地址中。
因此问题仍然存在:为什么在实践中无法使用巨大的常量时,语言为什么要这么点呢?
go ×8
constants ×2
types ×2
biginteger ×1
bit-shift ×1
const ×1
evaluation ×1
precision ×1
time ×1