Go中任意精度常数的目的是什么?

Jos*_*nig -1 constants go

Go具有任意大小和精度的无类型精确数字常量。该规范要求所有编译器支持至少256位的整数,并且至少浮动272位(尾数为256位,指数为16位)。因此,要求编译器忠实准确地表示如下表达式:

const (
    PI       = 3.1415926535897932384626433832795028841971
    Prime256 = 84028154888444252871881479176271707868370175636848156449781508641811196133203
)
Run Code Online (Sandbox Code Playgroud)

这很有趣......,但我无法找到任何方式实际使用任何这种持续超过64位的具体类型的最大精度int64uint64float64complex128(这只是一对float64值)。即使是标准库中的大数字类型 big.Intbig.Float也无法从大数字常量中进行初始化-必须从字符串常量或其他表达式中反序列化它们。

基本机制很明显:这些常量仅在编译时存在,并且必须强制为某个可在运行时表示的值才能在运行时使用。它们是仅在代码中和编译期间存在的语言构造。您无法在运行时检索常量的原始值;它不存储在已编译程序本身的某个地址中。

因此问题仍然存在:为什么在实践中无法使用巨大的常量时,语言为什么要这么点呢?

icz*_*cza 6

TLDR;Go的任意精度常量使您可以使用“实数”而不是“盒装”数,因此可以缓解“伪像”(例如上溢,下溢和无穷大的情况)。您可以以更高的精度工作,并且只需要将结果转换为有限精度,就可以减轻中间错误的影响。

Go Blog:常量:(强调是我回答您的问题)

数字常数存在于任意精度的数字空间中。它们只是常规数字。但是,当将它们分配给变量时,该值必须能够适合目标。我们可以声明一个非常大的常量:

const Huge = 1e1000
Run Code Online (Sandbox Code Playgroud)

(毕竟,这只是一个数字),但我们无法分配它,甚至无法打印出来。该语句甚至不会编译:

fmt.Println(Huge)
Run Code Online (Sandbox Code Playgroud)

错误为“常数1.00000e + 1000溢出float64”,这是正确的。但这Huge可能是有用的:如果可以在a范围内表示结果,则可以在具有其他常量的表达式中使用它,并使用这些表达式的值float64该声明,

fmt.Println(Huge / 1e999)
Run Code Online (Sandbox Code Playgroud)

可以10像预期的那样打印。

以相关的方式,浮点常量可能具有非常高的精度,因此涉及它们的算法会更加准确。数学包中定义的常量所提供的数字比float64。这是的定义math.Pi

Pi    = 3.14159265358979323846264338327950288419716939937510582097494459
Run Code Online (Sandbox Code Playgroud)

当该值分配给变量时,某些精度将丢失。分配将创建最接近高精度值的float64(或float32)值。这个片段

pi := math.Pi
fmt.Println(pi)
Run Code Online (Sandbox Code Playgroud)

版画3.141592653589793

可用的位数太多意味着Pi/2在分配结果之前,类似的计算或其他更复杂的求值方法可以具有更高的精度,从而使包含常数的计算更容易编写而又不损失精度。这也意味着在任何情况下都不会NaN在常量表达式中出现无穷大,软下溢和s之类的浮点拐角情况。(除以常数零是编译时错误,当所有内容都是数字时,就没有“不是数字”之类的东西。)

请参阅相关内容:Go如何对常量执行算术运算?