Go語言:未指定型別的常量(untyped int constant)和大整數的關係

ZeroZeroSeven發表於2024-11-07

執行下面的程式碼:

點選檢視程式碼
package main

import "fmt"

const (
	Big = 1 << 100
)

func needFloat(x float64) float64 {
	//fmt.Printf("%T", Big)  // It is wrong!
	return x * 0.1
}

func main() {
	fmt.Println(needFloat(Big))  // 1.2676506002282295e+29
}

當我嘗試print變數Big的型別時,發生了報錯,如下:

./prog.go:10:19: cannot use Big (untyped int constant 1267650600228229401496703205376) as int value in argument to fmt.Printf (overflows)

理由如下:
image
一個方面是,將Big的值傳遞給任何函式都需要為其分配一個實際型別。非型別化int可以變成任何整數型別或任何浮點型別(這取決於函式引數型別)。Go中單個整數值可以具有的最大實際型別是uint64,但任何型別的規則(即fmt.Println的引數型別)都更具體。它們將沒有任何其他型別資訊的無型別int轉換為int,在當前的CPU架構上為64位。這遠遠低於1<<100。
image
你現在可能想知道“為什麼我們甚至有大的常數?”答案是,你可以在常數表示式中使用大(和類似大小的值)。這些在編譯時進行評估,只有在使用了它們的值後才能得到實際的型別(粗略地說)。
所以你可以讓const Small=Big>>100,這相當於const Small=1,例如可以使用該常量,因為它的值可以輕鬆地放入int中。
例如,在實踐中出現的一個領域是計算地球表面各點之間的距離所需的計算。那裡使用的大量表示式可以不斷計算,這意味著與將所涉及的值分配給float64並對其進行數學運算相比,精度損失較小(因為浮點常數的精度是無限的)。

相關文章