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也无法从大数字常量中进行初始化-必须从字符串常量或其他表达式中反序列化它们。
基本机制很明显:这些常量仅在编译时存在,并且必须强制为某个可在运行时表示的值才能在运行时使用。它们是仅在代码中和编译期间存在的语言构造。您无法在运行时检索常量的原始值;它不存储在已编译程序本身的某个地址中。
因此问题仍然存在:为什么在实践中无法使用巨大的常量时,语言为什么要这么点呢?
TLDR;Go的任意精度常量使您可以使用“实数”而不是“盒装”数,因此可以缓解“伪像”(例如上溢,下溢和无穷大的情况)。您可以以更高的精度工作,并且只需要将结果转换为有限精度,就可以减轻中间错误的影响。
Go Blog:常量:(强调是我回答您的问题)
数字常数存在于任意精度的数字空间中。它们只是常规数字。但是,当将它们分配给变量时,该值必须能够适合目标。我们可以声明一个非常大的常量:
Run Code Online (Sandbox Code Playgroud)const Huge = 1e1000(毕竟,这只是一个数字),但我们无法分配它,甚至无法打印出来。该语句甚至不会编译:
Run Code Online (Sandbox Code Playgroud)fmt.Println(Huge)错误为“常数1.00000e + 1000溢出float64”,这是正确的。但这
Huge可能是有用的:如果可以在a范围内表示结果,则可以在具有其他常量的表达式中使用它,并使用这些表达式的值float64。该声明,Run Code Online (Sandbox Code Playgroud)fmt.Println(Huge / 1e999)可以
10像预期的那样打印。以相关的方式,浮点常量可能具有非常高的精度,因此涉及它们的算法会更加准确。给数学包中定义的常量所提供的数字比
float64。这是的定义math.Pi:Run Code Online (Sandbox Code Playgroud)Pi = 3.14159265358979323846264338327950288419716939937510582097494459当该值分配给变量时,某些精度将丢失。分配将创建最接近高精度值的
float64(或float32)值。这个片段Run Code Online (Sandbox Code Playgroud)pi := math.Pi fmt.Println(pi)版画
3.141592653589793。可用的位数太多意味着
Pi/2在分配结果之前,类似的计算或其他更复杂的求值方法可以具有更高的精度,从而使包含常数的计算更容易编写而又不损失精度。这也意味着在任何情况下都不会NaN在常量表达式中出现无穷大,软下溢和s之类的浮点拐角情况。(除以常数零是编译时错误,当所有内容都是数字时,就没有“不是数字”之类的东西。)
请参阅相关内容:Go如何对常量执行算术运算?