为何Ruby中相同运算的两种方法分别返回Rational和Integer?
问题解析:两种求和方法返回不同类型的原因
这个问题的核心在于初始值的差异以及Array#sum和Enumerable#inject的行为区别,咱们一步步拆解清楚:
1. 为什么第一个方法返回Rational?
先看这段代码:
(1..64).to_a.map.with_index { |_v, i| 2**(i - 1) }.sum.class # => Rational
这里的map.with_index是从索引0开始计数的,第一个迭代时i-1 = -1,而Ruby中整数的负指数幂会返回有理数类型(Rational)(比如2**-1等价于Rational(1, 2),不会返回浮点数)。
后面的迭代中,i从1到63,2**(i-1)的结果都是整数,但数组里已经混入了一个Rational元素。当调用Array#sum时,它会自动把所有元素转换为相同类型计算——因为数组里有Rational,所有整数都会被提升为Rational类型,最终结果自然是Rational。
2. 为什么第二个方法返回Integer?
再看这段代码:
(1..64).inject { |total,n| total + 2**(n-1)}.class # => Integer
不带初始值的inject会把集合的第一个元素作为初始total,也就是1(整数类型)。接下来每次迭代,n从2到64,2**(n-1)的结果都是整数,整数加整数的结果还是整数,整个计算过程中类型始终保持Integer,最终返回的就是Integer。
3. 如何让第一个方法也返回Integer?
只需要调整索引的起始值,让i从1开始即可:
(1..64).map.with_index(1) { |_v, i| 2**(i - 1) }.sum.class # => Integer
with_index(1)让索引从1开始,第一个元素就是2**0=1(整数),整个数组都是整数类型,sum的结果自然就是Integer了。
内容的提问来源于stack exchange,提问作者Altons
相关产品推荐
相关产品推荐

