Project1

标题: 关于Float类型与Fixnum类型的指针 [打印本页]

作者: IamI    时间: 2010-8-20 11:04
标题: 关于Float类型与Fixnum类型的指针
  1. # Float
  2. a = 3.0/5.0
  3. b = 3.0/5.0
  4. c = b
  5. p a.__id__,b.__id__,c.__id__
  6. p a - b == 0,a == b
  7. # Fixnum
  8. a = 10/5
  9. b = 10/5
  10. c = b
  11. p a.__id__,b.__id__,c.__id__
  12. p a - b == 0,a == b
复制代码
代码如上。发现浮点数是指针型,每次即使值相同也不返回同一个对象,而Fixnum则全然不同。
通过解析法亦可发现,在Ruby的Marshalling过程中,Float占用一个引用位置,而Fixnum则不占用。
求解。如能说明Fixnum(value class)的工作原理更佳。

总括:为什么Float是引用类,而Fixnum是值类?
作者: 六祈    时间: 2010-8-20 11:16
回复 IamI 的帖子
不是都是值类么,Float似乎是精确度的缘故所以不相等
   
作者: 八云紫    时间: 2010-8-20 11:21
浮点数的相等判断是需要一个精度问题的。

  1. #define ZERO 10^(-10)

  2. float a,b;
  3. if(a - b < ZERO)
  4.   return true;
  5. else
  6. retrun false;
复制代码

作者: 紫苏    时间: 2010-8-20 14:04
可能有以下几个原因:
1、在 32 位选址的 CPU 架构下,一个指针占用 32 位;Fixnum 的表示方法是 31 位 2's complement 补码形式;Float 的表示方式是本地的双精度浮点类型,大部分平台下使用的是 IEEE-754 标准,需要(但不一定是) 64 个字节。所以 Fixnum 可以作为直接值直接保存在 32 位的指针本身,而 64 位的 Float 却不行
2、整数作为直接值可以减少内存消耗——引用类型需要频繁进行堆内存操作,而在有垃圾回收机制的高级语言里,为了有效地分配和回收内存,堆通常是链式结构,垃圾回收器要频繁地查找、删除、插入、合并可用的内存节点并归组到一起以减少内存碎片,显然链式堆的任何内存操作都注定慢于连续内存结构(数组结构)的栈内存操作(VALUE 指针是在栈上)
3、虽然在计算机领域里定点数和浮点数的集合都是离散的,但浮点数集合的大小远远大于定点数集合。对于定点数,我们可以用某种算法给每个定点数一个固定的 object_id,而如果要让每一个可表示的浮点数也有这样的固定 object_id,其开销是不堪设想的。实际在应用的时候,很少会出现两个完全相同的浮点数的场合,从这一点上来看似乎也没有必要让浮点数拥有整数、符号、字符串那样的“扣留”机制

Fixnum 的工作原理:
Fixnum 和 NilClass、TrueClass、FalseClass 都是 Ruby 中的直接类型,这些类型的数据不会以复式结构体来表示,而是直接保存在了 VALUE 型指针里
Ruby 舍弃了 VALUE 的最低位作为“定点数标志位”,指定了这个数据是否是 Fixnum,所以在 Ruby 中 Fixnum 只有 31 位(VALUE 的值至少有 32 位),并且是被整体左移了一位,也就是数据存储在高 31 位中
与之平行存在的其它三种直接值类型分别是如此存储的:
VALUE 的值如果是 0b0000,那就是 false;如果是 0b0010,那就是 true;如果是 0b0100,那就是 nil;符号类型也有一个标志掩码 0x0e,即最低 8 位(最低字节)如果是 0b00001110 的话 VALUE 表示的就是一个符号类型。可以看出以上各项之间并没有交集
其余的引用类型,由于其本身是复式的结构体数据( 由 RBasic 衍生出来的结构体),所以是由 VALUE 这个指针来维护其地址的,由于内存对齐机制,无论如何这些结构体的首地址都必然是 4 的倍数,即最低两位为 0,所以引用类型的地址也不会和直接值的表示方式产生冲突
至于 object_id,则是直接返回 VALUE 的值。Fixnum 的最低位是 1,所以 Fixnum 的 object_id 必然是单数,且由于真实数据向左偏移了一位,object_id 和 数据本身的关系应该是 数据本身*2+1




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1