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

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

const (
    PI       = 3.1415926535897932384626433832795028841971
    Prime256 = 84028154888444252871881479176271707868370175636848156449781508641811196133203
    )

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

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

所以问题仍然存在:当大量常量无法在实践中使用时,为什么该语言要支持这些常量呢?


汪汪一只猫
浏览 91回答 0
0回答

暮色呼如

太长了;Go 的任意精度常量使您可以使用“真实”数字而不是“盒装”数字,因此可以缓解溢出、下溢、无穷大极端情况等“伪影”。您可以以更高的精度进行工作,并且只需将结果转换为有限精度,从而减轻中间误差的影响。数字常量存在于任意精度的数字空间中;它们只是普通数字。但是,当将它们分配给变量时,该值必须能够适合目标。我们可以声明一个非常大的值的常量:const Huge = 1e1000——毕竟,这只是一个数字——但我们无法分配它,甚至无法打印它。该语句甚至无法编译:fmt.Println(Huge)错误是“constant 1.00000e+1000 溢出 float64”,这是正确的。但Huge可能有用:我们可以在具有其他常量的表达式中使用它,并且如果结果可以在 a 范围内表示,则可以使用这些表达式的值float64。该声明,fmt.Println(Huge / 1e999)打印10,正如人们所期望的那样。与此相关的是,浮点常量可能具有非常高的精度,因此涉及它们的算术更加准确。math包中定义的常量的位数比float64. 这是 的定义math.Pi:Pi    = 3.14159265358979323846264338327950288419716939937510582097494459当将该值分配给变量时,一些精度将会丢失;赋值将创建最接近高精度值 的float64(或float32) 值。这个片段pi := math.Pi fmt.Println(pi)打印3.141592653589793。拥有如此多的可用数字意味着类似计算Pi/2或其他更复杂的计算可以在分配结果之前具有更高的精度,从而使涉及常量的计算更容易编写而不会损失精度。这也意味着常量表达式中不会出现无穷大、软下溢和 s 等浮点极端情况NaN。(除以常量零是一个编译时错误,当一切都是数字时,就不存在“不是数字”这样的事情。)
打开App,查看更多内容
随时随地看视频慕课网APP