我知道 Ruby 有 Float 用于实数,Fixnum 和 Bignum 用于 int。但是这种类型的大小呢?
a = 1.23 // 一个浮点数的大小(以字节为单位)?
b = 1 // 一个 Fixnum 的大小(以字节为单位)?
c = 2**65 // = 一个 Bignum 的大小(以字节为单位)?
我正在尝试寻找标准或规范
我知道 Ruby 有 Float 用于实数,Fixnum 和 Bignum 用于 int。
这不是真的。
Float不代表实数,它代表浮点数。事实上,在一般情况下,在物理计算机中表示实数是不可能的,因为它需要无限的内存。
Fixnum并且Bignum不是 Ruby 的一部分。红宝石只有Integer. Ruby 规范允许不同的实现具有特定于实现的子类,但是这些子类特定于特定的实现(例如 YARV、Opal、TruffleRuby、Artichoke、JRuby、IronRuby、MRuby 等),它们没有任何关系与红宝石。
事实上,即使知道实现还不够,您还必须知道确切的版本。例如,YARV 过去有Fixnum和Bignum作为子类,但现在没有了,它只有Integer. 甚至在拥有它们的时候,这仍然不够,因为它们实际上根据平台的不同而具有不同的尺寸。
但是这种类型的大小呢?
a = 1.23 // 一个浮点数的大小(以字节为单位)?
b = 1 // 一个 Fixnum 的大小(以字节为单位)?
c = 2**65 // = 一个 Bignum 的大小(以字节为单位)?
我正在尝试寻找标准或规范
以下是ISO/IEC 30170:2012信息技术 — 编程语言 — Ruby规范对此事的看法 [我的粗体强调]:
15.2.8
Integer15.2.8.1 一般说明
类的实例
Integer表示整数。这些整数的范围是无限的。然而,可计算的实际值取决于资源限制,超出资源限制时的行为是实现定义的。[…]
类的子类
Integer可以定义为内置类。在这种情况下:
- 该类
Integer不应有其直接实例。应创建Integer类的子类的直接实例,而不是类的直接实例。Integer- 如果在类的所有子类中都定义了实例方法,则
Integer不需要在类Integer本身中定义该类的实例方法Integer。- 对于类的每个子类
Integer,其实例值的范围可能是有界的。
ISO Ruby 语言规范没有规定Integers 的任何特定大小或表示,也没有指定任何查询此信息的方法。
15.2.9
Float15.2.9.1 一般说明
该类的实例
Float表示浮点数。 类实例值的精度Float是实现定义的;但是,如果符合标准的处理器的底层系统支持 IEC 60559,则该类实例的表示Float应为 IEC 60559, 3.2.2 中规定的 64 位双精度格式。
ISO Ruby 语言规范不要求Floats 有任何特定的大小或表示,除非底层系统支持 ISO/IEC 60559,在这种情况下,表示必须是 ISO/IEC 60559 binary64双浮点数。ISO Ruby 语言规范没有指定任何查询此信息的方法。
ruby/spec 没有说明Float. 事实上,什么都不说是非常小心的。例如,如果您查看的规范Float#prev_float,您会发现他们非常小心地指定 的行为,Float#prev_float而从未提及实际精度。
ruby/specInteger#size 确实说明了特定机器整数的大小(以字节为单位)。然而,不幸的是,ruby/spec 是Ruby 编程语言行为规范和YARV Ruby 实现行为规范的混合体。我觉得这个规范更像是后者。
例如,在 YARV 中,fixnums 和 bignums 之间的分界点在32 位平台上是 2 31 ,在 64 位平台上是 2 63,但在 JRuby 上,在 32 位和 64 位平台上都是 2 64(我认为 TruffleRuby 是相同的)。因此,3000000000 在 32 位 YARV 上将是一个大数字,但在 64 位 YARV 和 JRuby 上是一个固定数字,而 100000000000000000000 在 32 位和 64 位 YARV 上都是一个大数字,但即使在 32 位 JRuby 上也是一个固定数字。对于 Opal,我认为截止点再次不同,我认为是 2 53。其他实现甚至可能根本不区分 fixnums 和 bignums,或者它们可能具有三种或更多种不同类型的整数。
此外,请务必记住,此规范仅指定方法的返回值Integer#size。它没有说这实际上是Integer必须在内存中表示的方式。
Fixnum顺便说一句,当我在上面说过并且Bignum已从 YARV 中删除时,您可能会困惑为什么我在 YARV 中谈论 fixnums 和 bignums 。好吧,原因是单独的类已被删除,但优化仍然存在。另一件事是:ISO Ruby 语言规范说您可以拥有特定于实现的子类Integer,但它没有说明这些类的用途。ISO Ruby 语言规范既不强制实现者为其子类优化实现,也不强制实现者为其实现特定的优化提供子类。
将其与 YARV 的flonums进行比较,后者是 62 位Float的优化表示,但它们没有自己的类。
所以,简而言之:ISO Ruby 语言规范没有说明Integers 的大小,但它确实说如果底层系统支持 ISO/IEC 60559,那么表示必须是 ISO/IEC 60559 binary64双浮动。但是,对于底层系统不支持 ISO/IEC 60559 的情况,它确实没有说明大小或表示形式。
ruby/spec 小心地不指定任何关于Floats 的大小,但它确实指定了Integer#size方法的返回值。然而,它并没有指定这个返回值必须以任何方式对应于Integers 的实际表示方式。
以下是YARV中的 RDocInteger#size必须说的 [我的粗体强调]:
size→int返回(机器相关)的机器表示中的字节数。
int
所以,它只说它返回机器表示中的字节数Integer ,但并不一定是它实际表示的方式。它清楚地表明该值取决于机器。