3

我知道 Ruby 有 Float 用于实数,Fixnum 和 Bignum 用于 int。但是这种类型的大小呢?

a = 1.23 // 一个浮点数的大小(以字节为单位)?

b = 1 // 一个 Fixnum 的大小(以字节为单位)?

c = 2**65 // = 一个 Bignum 的大小(以字节为单位)?

我正在尝试寻找标准或规范

4

2 回答 2

3

Fixnumsize方法

2**65.size # => 256
1.size # => 8

浮动- 从这篇SO 帖子以及 Stefan 在评论中指出的内容,它们是 64 位的。

Stringbytesize方法

 "test".bytesize # 4
于 2021-03-21T07:55:30.610 回答
2

我知道 Ruby 有 Float 用于实数,Fixnum 和 Bignum 用于 int。

这不是真的。

Float不代表实数,它代表浮点数。事实上,在一般情况下,在物理计算机中表示实数是不可能的,因为它需要无限的内存。

Fixnum并且Bignum不是 Ruby 的一部分。红宝石只有Integer. Ruby 规范允许不同的实现具有特定于实现的子类,但是这些子类特定于特定的实现(例如 YARV、Opal、TruffleRuby、Artichoke、JRuby、IronRuby、MRuby 等),它们没有任何关系与红宝石。

事实上,即使知道实现还不够,您还必须知道确切的版本。例如,YARV 过去有FixnumBignum作为子类,但现在没有了,它只有Integer. 甚至在拥有它们的时候,这仍然不够,因为它们实际上根据平台的不同而具有不同的尺寸。

但是这种类型的大小呢?

a = 1.23 // 一个浮点数的大小(以字节为单位)?

b = 1 // 一个 Fixnum 的大小(以字节为单位)?

c = 2**65 // = 一个 Bignum 的大小(以字节为单位)?

我正在尝试寻找标准或规范

以下是ISO/IEC 30170:2012信息技术 — 编程语言 — Ruby规范对此事的看法 [我的粗体强调]:

15.2.8Integer

15.2.8.1 一般说明

类的实例Integer表示整数。这些整数的范围是无限的。然而,可计算的实际值取决于资源限制,超出资源限制时的行为是实现定义的。

[…]

类的子类Integer 可以定义为内置类。在这种情况下:

  • 该类Integer不应有其直接实例。应创建Integer类的子类的直接实例,而不是类的直接实例。Integer
  • 如果在类的所有子类中都定义了实例方法,则Integer不需要在类Integer本身中定义该类的实例方法Integer
  • 对于类的每个子类Integer,其实例值的范围可能是有界的。

ISO Ruby 语言规范没有规定Integers 的任何特定大小或表示,也没有指定任何查询此信息的方法。

15.2.9Float

15.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必须说的 [我的粗体强调]:

sizeint

返回(机器相关的机器表示中的字节数。int

所以,它只说它返回机器表示中的字节数Integer 但并不一定是它实际表示的方式。它清楚地表明该值取决于机器。

于 2021-03-21T12:20:19.153 回答