这次谈一谈Ruby的数据类型。
Ruby和Python是很相像的编程语言,数据类型有很多相通的地方,如果你对Python语言非常熟悉,学习Ruby的数据类型也不会困难。
一、数字
整数(Integer)
整数的存储一般占4个字节,而对Ruby来说,只要整数的范围在[2-31,231),即不越界的话,它就属于Fixnum类型,只要超出了这个范围,Ruby会将数字类型自动转换为Bignum,范围[2-63,263)
以上是我在教程里看的,随后自己试了一下:
b=2**16
puts b,b.class
b*=2**31
puts b,b.class
b**=31
puts b,b.class
输出为:
65536
Integer
140737488355328
Integer
3987527419489428978934891797539519074407964567436787186133619573501046471683744380659059161937985807259468675374073145280737497721642052937815042118700682845870910169347677909227832368695028770450412842403709263345644496696985054600802825392442509910854943490420673962888628144965097175804215761432440180478119397118650550445707581358533929378076799381878425215674358616643302551330255407000153121771310799585481738504362758992372927823872
Integer
(其实并没有看出来什么区别,而且数字支持的范围也不仅仅是[2-63,263))
又看了这个链接,相同的输入输出了不同的东西
https://blog.csdn.net/ruby_cn/article/details/197985
最后查了一下是ruby版本的问题。在ruby2.2的官方文档中还有Fixnum和Bignum的类,现在最新的2.6.2版本中已经把它们去掉了。
那么我们以最新的版本为准,我的理解是这样的:
- 整数类Integer不可再分,支持任意大小和正负
- ruby为Integer变量自动分配存储空间,数值增减,数值空间也会随之增减。具体见代码:
1.size #=> 8
-1.size #=> 8
2147483647.size #=> 8
(256**10 - 1).size #=> 10
(256**20 - 1).size #=> 20
(256**40 - 1).size #=> 40
整数使用部分:
几种常见的整数应用实例:
1_234 # 带有下划线的十进制,_对数值没有用,可以作为标记(比如千分符)用
0377 # 八进制
0xff # 十六进制
0b1011 # 二进制
"a".ord # "a" 的字符编码
?\n # 换行符(0x0a)的编码
还有一点需要提的是:Integer可以取二进制位的值哦
p 3[0] #相当于3%2
=>1
print 11[0],11[1],11[2],11[3],11[4],11[-1] #负数index全部返回0,没有用处
=>110100
小数
下面我说的有关小数范围的内容可能很细,读者可以略过,去读小数的使用部分。这里跳转
首先,我们必须了解: 计算机在存储一个小数的变量时是以二进制形式存储的,所以在小数约进约出的时候,计算机也会按照二进制计算。脱离二进制,空谈小数的约位是没有意义的。
比如下面这个简单的程序要脱离二进制解释就很难说通,为什么小数位是从0到不是0再到是0?
print ("%.70f"%0.1)
=> 0.1000000000000000055511151231257827021181583404541015625000000000000000
用二进制的思维去想,0.1实际上是二进制0.000(1100)的循环,Ruby保留了若干个二进制位,根据余位的多少进行进位或者是借位。再转化为十进制的时候,就会有小数点后面一定范围内的误差。
前面有零是因为前面计算都是正确的,后面是零是因为:由于除以2-n不管n有多大总会被除尽,二进制转化为十进制后不会出现循环
那么Ruby保留位数是多少呢?通过实验来证明一下:
a=1+1.0/2**52
puts ("%.60f"%a)
=> 1.000000000000000222044604925031308084726333618164062500000000
a=1+1.0/2**53
puts ("%.60f"%a)
=> 1.000000000000000000000000000000000000000000000000000000000000
a=0.5+1.0/2**53
puts ("%.60f"%a)
=> 0.500000000000000111022302462515654042363166809082031250000000
a=1.5+1.0/2**53
puts ("%.60f"%a)
=> 1.500000000000000000000000000000000000000000000000000000000000
a=-1+1.0/2**53
puts ("%.60f"%a)
=> -0.999999999999999888977697537484345957636833190917968750000000
可以看出,Ruby保留小数时,主要看的是有效数字的部分。二进制有效数字部分为:
[-253,253-1)
所以会出现这样尴尬的情况:
a=1111111111111111111.1
puts ("%.3f"%a)
=> 1111111111111111168.000
既然小数的保留是看有效数字位数,科学记数法的指数自然也需要限制范围:
a=1.0*2**(2**10-1)
puts ("%.3f"%a)
=> 898846567431157...12068608.000
a=1.0*2**(2**10)
puts ("%.3f"%a)
=> Inf
a=1.0*2**(-0b10000110010)
puts ("%.1050f"%a)
=> 0.000...0000000556268464626800345...821289062500000000000000000000000000
a=1.0*(2**(-(0b10000110011)))
puts ("%.1050f"%a)
=> 0.000...0
可见,指数范围是[-0b1000110010,2**10),?搞不懂为什么范围这么奇怪,欢迎留言批评指正。
小数使用部分:
%
%运算符在小数中仍然可以使用:
a=3.4%2
puts (a)
=> 1.4
a=3.4%1.1
puts (a)
=> 0.09999999999999964
a=-3.4%(-1.1)
puts (a)
=> -0.09999999999999964
a=3.4%(-1.1)
puts (a)
=> -1.0000000000000004
用法自己体会。
rationalize
0.3.rationalize #=> (3/10)
1.333.rationalize #=> (1333/1000)
1.333.rationalize(0.01) #=> (4/3)
这里0.01参数是指1.333-0.01<=4/3<=1.333+0.01
round
默认四舍五入,即half: :up,也可以指定half。
half: :even是遇到.5会约到最近的偶数
2.5.round(half: :up) #=> 3
2.5.round(half: :down) #=> 2
2.5.round(half: :even) #=> 2
3.5.round(half: :up) #=> 4
3.5.round(half: :down) #=> 3
3.5.round(half: :even) #=> 4
(-2.5).round(half: :up) #=> -3
(-2.5).round(half: :down) #=> -2
(-2.5).round(half: :even) #=> -2