Subject: Re: Scalar class?

正木です。

|[ruby-math:00725] Re: Scalar class?
|From: matz / ruby-lang.org (Yukihiro Matsumoto)
|n=1なstepであるuptoはStringに定義されています。任意のnを定義
|できる必要はないのではないでしょうか。

すみません。upto に気付きませんでした。前の mail [ruby-math:00724]
は最後の行を除いてすべて撤回します。


||ただし step を Float には拡張しない方が良いという意見は変わりません。
|
|うむ、それはなぜ?

Float では数学的な整合性がとれないからです。以下の意見に全面的に
賛成です。

|[ruby-math:00726] Re: Scalar class?
|From: Masahiro TANAKA <masa / ir.isas.ac.jp>
|このように、どう動作するかが浮動小数点数の内部まで立ち入らないと
|予想できないようなメソッドを*標準*で用意するというのは、あまり
|望ましくはないと思いますがいかがでしょうか。
|(ユーザが自己責任で用意するのは構わないと思いますが)

要するに Float を扱う時は危険を承知の上で自己責任でやって下さいと
いうことです。

標準で提供するのは反対ですが、
以下、自己責任でということで一寸考えてみました。

田中さんがあげた例はわざとうまく行かない定義を使っているので
次のような
class Float
  def step(max,step)
    i=0
    loop do
      x= self+i*step
      break if x>max
      yield x
      i+=1
    end
  end
end
定義にしたら、うまく行かない例を探すのにもう少し苦労したはずです。
上の code は現在の Intel の仕様では(ということは Ruby でも)
(1.0/n)*n <= 1.0
となる(らしい)事を利用しています。ですから
(1.0/n)*n < 1.0
となる n(49,98,103,...)を探せば失敗例はすぐ作れます:
(0.0).step(0.9999999999999999, 1.0/103){|x| p x}
は 1 まで出力します。
(まさかこれが期待どうりの結果だという人はいないと思いますが)

|class Float
|  EPSILON=2.2204460492503131E-16
|  def step(max,step)
|    n = (max-self)/step
|    n = (n + n*EPSILON).floor + 1
|    n.times{|i| yield i*step+self}
|  end
|end

これも上と同じ例で失敗します。
仮に絶対に大丈夫な code が書けたとしても
(0.0).step(1.0, 1.0/103){|x| p x}
の最後の出力は本当は(精度をあげれば)
0.99999999999999988897…
なのは気持悪いといった問題には対処できません。