From: Masa Date: 2014-04-21T00:52:06+09:00 Subject: [ruby-list:49798] Re: Range class? まつもとさま、皆様 坂野正明です。 まつもとさん、早速のそして大変明快なご返事を ありがとうございました! お蔭様で多くの疑問が解けました! 一点、Range の要素が Rational と Floatで違いがでるのが まだ分かりませんが……(後述します)。 以下、それぞれご返事を書きます。 2014年 4月 20日(日)10:58 pm に Yukihiro Matsumoto さんは書きました: > まつもと ゆきひろです > > Rangeの奇妙な振る舞いを理解するためには、Rangeのメソッドには、 > Enumerableとして振る舞うものと、Intervalとして振る舞うものの > の両方があることに注意しなければなりません。 > > Enumerableとして振る舞うものは離散的で、eachメソッドが生成す > る要素を使います。Rangeの場合、eachは始点から1.0ずつ離れた値 > が生成されます(数値の場合)。 そうだったのですか! 始点から 1.0 (Float?)というステップだったとは 存じませんでした。 たとえば、 irb> (1.0..5).each {|n| print n, ' ' } TypeError: can't iterate from Float from (irb):30:in `each' というように、始点が Float であればそもそも Exception が発生します。 だから、例外無しに succ() が使われていると 思い込んでいたものでした……。 # 内部の実装として、数値の場合は数値計算した方が # 速いだろうとは(言われてみれば)想像できますが。 > Intervalとして振る舞うものは連続的で始点(begin)と終点(end)の > 大きさで決まります。 > > たとえば、include?はeachを使い、cover?は始点と終点の間の比較 > で判定します。 はい、分かります。 first と begin との違いも同様ですよね。その場合は 数値を例外として。 > ですから、ご指摘のメソッドではこのような事情があります。 > > maxは終点を、minmaxは最終要素を返します。 > sizeはeachの与える要素数を返します。 > > 例として「0.5...5」は「0.5から1.0刻みで5.0を越えない要素の数」 > という意味になり、それらの要素は[0.5, 1.5, 2.5, 3.5, 4.5]です > から「(0.5...5).size」は5になります。 > > 理解(or 納得)の一助になりましたでしょうか? 明快です。 ありがとうございました。 四捨五入か何かと疑うことになったのは、偶然、私が 使った例の始点が 1.5 という値だったからというだけですね。 参りました。 一点だけ、まだそれでは説明できないのは、以下の例です。 | irb> (Rational(1,2)...5).size # => 4 | irb> (0.5...5).size # => 5 # Why not 4?? Rational の方が(だけ?)整数化されているように、 もしくはそれを下回らない最小の整数になっているような 挙動ですね。 上の違い、特に max/minmax の方は、マニュアルに書かれて あれば親切かも知れませんね。 # 現実的に問題になることは相当稀でしょうが……。 include?/cover? や first/begin と違って(←これらは、 最初に理解した時に、命名の見事さに感動したものでした! 短い名にして体をよく表している、と)、挙動に違いがある ことが予想あるいは理解しにくいと恐れますもので。 坂野正明