数值类
在数值类中,有像-1、0、1、10 这样的表示整数的 Integer 类,也有像 0.1、3.141592 这样的具有精度的、表示浮点小数的 Float 类。
这些数值类都被定义为了 Numeric 类的子类。另外, Integer 类又可以分为两种,一种是表示计算机硬件可以处理的数值的 Fixnum 类,另外一种是表示比 Fixnum 更大的数值的 Bignum 类。
Numeric的子类:
Numeric:Integer整数、Float浮点小数、Rational有理数、Complex复数
Integer:Fixnum普通的整数、Bignum大整数
Rational 对象用“Rational( 分子 , 分母 )”的形式定义。我们可以使用 numerator 方法和 denomination 方法获取 Rational 对象的分子和分母。
Complex 对象用“Complex( 实数 , 虚数 )”的形式定义。我们可以使用 real 方法和 imaginary 方法获取 Complex 对象的实数与虚数。
在整数和小数的末尾添加 r 可以得到 Rational 对象,添加 i 可以得到 Complex 对象。
数值类转换
将 Integer 对象转换为 Float 对象时,可以使用 to_f 方法。相反,使用 to_i 方法则可以将Float 对象转换为Integer 对象(Integer#to_i 方法和 Float#to_f 方法返回与接收者一样的值)。另外,也可以把字符串转换为数值。
p 10.to_f #=> 10.0
p 10.8.to_i #=> 10
p -10.8.to_i #=> -10
p "123".to_i #=> 123
p "12.3".to_f #=> 12.3
Float#to_i 方法返回的结果会把小数点以后的值去掉。我们用 round 方法对小数进行四舍五入的处理。可以用参数指定取几位小数,如果参数为负数,则往小数点左边(即整数部分)的位数取整。
p 0.12.round(1) #=> 0.1
p 0.18.round(1) #=> 0.2
p 1.2.round #=> 1
p 1.8.round #=> 2
p 120.round(-2) #=> 100
p 180.round(-2) #=> 200
返回比接收者大的最小整数用 ceil 方法,返回比接收者小的最大整数用 floor 方法。
p 1.5.ceil #=> 2
p -1.5.ceil #=> -1
p 1.5.floor #=> 1
p -1.5.floor #=> -2
我们还可以将数值转换为 Rational 对象和 Complex 对象,分别使用 to_r 和 to_c 方法。
p 1.5.to_r #=> (3/2)
p 1.5.to_c #=> (1.5+0i)
随机数
随机性一般有以下特质:
- 没有规则和法则依据
- 一定范围内的数会均等地出现
我们可以用 Random.rand 方法得到随机数。不指定参数时, Random.rand 方法返回比1小的浮点小数。参数为正整数时,返回 0 到该正整数之间的数值。
p Random.rand #=> 0.18905778941140605
p Random.rand(100) #=> 67
p Random.rand(100) #=> 91
程序不能生成真正的随机数,只能通过某种算法生成看起来像随机数的值,这样的随机数称为伪随机数。生成伪随机数需要以某个值为基础,这个值称为随机数的种子。伪随机数终究只是通过计算得到的数值,只要随机数的种子一样,那么得到的值就有可能重复出现。使用 Random.new 方法初始化随机数生成器,然后再使用 Random#rand 方法,就可以对 Random 对象指定随机数种子,从而生成随机数。
r1 = Random.new(1) # 初始化随机数组
p [r1.rand, r1.rand] #=> [0.417022004702574, 0.7203244934421581]
r2 = Random.new(1) # 再次初始化随机数组
p [r2.rand, r2.rand] #=> [0.417022004702574, 0.7203244934421581]
Random.new 方法不指定参数的情况下,则会用随机生成的随机数种子初始化 Random 对象,因此每次得到的随机数组也会不一样。
r1 = Random.new
p [r1.rand, r1.rand] #=> [0.49452535392946817, 0.34141702823098863]\
r2 = Random.new
p [r2.rand, r2.rand] #=> [0.9464262066747281, 0.01911968591048996]
计数
除了数值计算外,Integer 类还能计算处理的次数、数组的元素个数等。接下来介绍的方法就是按照数值指定的次数执行循环处理的迭代器。
n.times{|i| ... } 循环 n 次,从 0 到 n-1 的值会被依次赋值给块变量i。
ary = []
10.times do |i|
ary << i # 把 i 作为元素追加到数组
end
p ary #=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
from.upto(to){|i| ... } 从 from 开始循环对 i 进行加 1 处理,直到 i 等于 to。from 比to 大时不会执行循环处理。
ary = []
2.upto(10) do |i|
ary << i
end
p ary #=> [2, 3, 4, 5, 6, 7, 8, 9, 10]
from.downto(to){|i|...} 从 from 开始循环对 i 进行减 1 处理,直到 i 等于 to。from 比 to 小时不会执行循环处理。
ary = []
10.downto(2) do |i|
ary << i
end
p ary #=> [10, 9, 8, 7, 6, 5, 4, 3, 2]
from.step(to, step){|i|...} 从 from 开始循环对 i 进行加 step 处理,直到i 等于 to。step 为正的情况下,from 比 to 大时不会执行循环处理。step 为负的情况下,from 比 to 小时不会执行循环处理。
ary = []
2.step(10, 3) do |i|
ary << i
end
p ary #=> [2, 5, 8]
ary = []
10.step(2, -3) do |i|
ary << i
end
p ary #=> [10, 7, 4]
如果不对 times、upto、downto、step 的各方法指定块,则会返回 Enumerator 对象。这样,之前通过 step 方法的块获取的一连串数值,就同样也可以通过 Enumerator#collect 方法获取。
ary = 2.step(10).collect{|i| i * 2}
p ary #=> [4, 6, 8, 10, 12, 14, 16, 18, 20]