栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Go如何对常数执行算术运算?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Go如何对常数执行算术运算?

简短摘要(TL; DR)在答案的结尾。

无类型的任意精度常量在运行时不存在,常量仅在编译时(在编译期间)存在。话虽如此,Go不必在运行时以任意精度表示常量,而仅在编译应用程序时。

为什么?因为常量不会被编译到可执行二进制文件中。他们不必是。让我们举个例子:

const Huge = 1e1000fmt.Println(Huge / 1e999)

有一个不变

Huge
源代码
(并会在包对象),但它不会出现在你的可执行文件。相反,
fmt.Println()
将记录一个传递给它的值(类型为)来记录对函数的调用
float64
。因此在可执行文件中,只会记录一个
float64
10.0
1e1000
可执行文件中没有任何数字的迹象。

float64
类型派生自 无类型 常量的 默认
类型。是浮点文字。验证:
__
Huge``1e1000


const Huge = 1e1000x := Huge / 1e999fmt.Printf("%T", x) // Prints float64

回到任意精度:

规格:常数:

数字常数表示任意精度的精确值,并且不会溢出。

因此,常数表示任意精度的精确值。如我们所见,无需在 运行时 以任意精度表示常量,但编译器仍必须在 编译时 执行某些 操作 。它 确实

显然,“无限”精度无法解决。但是没有必要,因为源代码本身不是“无限的”(源大小是有限的)。但是, 允许
真正任意精度仍然不切实际。因此,规范为此提供了一些自由给编译器:

实现限制:尽管数字常量在语言中具有任意精度,但是编译器可能会使用内部表示形式来实现它们,而精度有限。也就是说,每个实现都必须:

  • 用至少256位表示整数常量。
  • 表示浮点常数,包括复数常数的部分,尾数至少为256位,带符号的指数至少为32位。
  • 如果无法精确表示整数常数,则给出错误。
  • 如果由于溢出而无法表示浮点数或复数常量,则给出错误。
    *如果由于精度限制而无法表示浮点数或复数常数,则四舍五入到最接近的可表示常数。这些要求既适用于文字常量,也适用于评估常量表达式的结果。

但是,还请注意,当上述所有内容都存在时,标准包为您提供了仍然可以以“任意”精度表示和使用值(常数)的方法,请参见package

go/constant
。您可以查看其来源,以了解其实现方式。

实现在中

go/constant/value.go
。表示此类值的类型:

// A Value represents the value of a Go constant.type Value interface {    // Kind returns the value kind.    Kind() Kind    // String returns a short, human-readable form of the value.    // For numeric values, the result may be an approximation;    // for String values the result may be a shortened string.    // Use ExactString for a string representing a value exactly.    String() string    // ExactString returns an exact, printable form of the value.    ExactString() string    // Prevent external implementations.    implementsValue()}type (    unknownVal struct{}    boolVal    bool    stringVal  string    int64Val   int64         // Int values representable as an int64    intVal     struct{ val *big.Int }   // Int values not representable as an int64    ratVal     struct{ val *big.Rat }   // Float values representable as a fraction    floatVal   struct{ val *big.Float } // Float values not representable as a fraction    complexVal struct{ re, im Value })

如您所见,该

math/big
包用于表示无类型的任意精度值。
big.Int
例如(来自
math/big/int.go
):

// An Int represents a signed multi-precision integer.// The zero value for an Int represents the value 0.type Int struct {    neg bool // sign    abs nat  // absolute value of the integer}

nat
(来自
math/big/nat.go
)在哪里:

// An unsigned integer x of the form////   x = x[n-1]*_B^(n-1) + x[n-2]*_B^(n-2) + ... + x[1]*_B + x[0]//// with 0 <= x[i] < _B and 0 <= i < n is stored in a slice of length n,// with the digits x[i] as the slice elements.//// A number is normalized if the slice contains no leading 0 digits.// During arithmetic operations, denormalized values may occur but are// always normalized before returning the final result. The normalized// representation of 0 is the empty or nil slice (length = 0).//type nat []Word

最后

Word
是(来自
math/big/arith.go

// A Word represents a single digit of a multi-precision unsigned integer.type Word uintptr

摘要

在运行时: 预定义
类型提供有限的精度,但是您可以使用某些包(例如

math/big
和)“模拟”任意精度
go/constant
。在编译时:常量似乎提供了任意精度,但实际上,编译器可能无法做到这一点(不必这样做);但是规范仍然为所有编译器必须支持的常数提供了最低的精度,例如,整数常数必须至少以256位(32字节)表示(相比之下
int64
,“仅”
8字节)。

创建可执行二进制文件时,必须转换常量表达式的结果(具有任意精度),并用有限精度类型的值表示-这可能是不可能的,因此可能导致编译时错误。请注意,只有
结果( 而不是中间操作数)必须转换为有限精度,常数运算可以任意精度执行。

规范未定义如何实现这种任意精度或增强精度,

math/big
例如,将数字的“数字”存储在切片中(其中,数字不是以10为基数表示的数字,而“数字”
uintptr
是类似于base的数字)。在4位元架构上显示4294967295,在64位元架构上甚至更大)。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/447917.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号