けいじゅ@日本ラショナルソフトウェアです.

In [ruby-math :00576 ] the message: "[ruby-math:00576] Re: int / int -
> ? ", on Aug/20 19:03(JST) Shin-ichiro HARA writes:

>原です。
>なんかお盆明けてみると、ずいぶん情勢が変わっていて、、、

ども. 御久しぶりです. 

> >int/intですが, やはり結果はRationalにするのがよいと強く思うようになりま
> >した.
>
>うっ。まじっすか。(^_^;

まえから, int/int->Rational のほうがよいとは思っていたんですが、
int/int->int の方がパフォーマンスの面とか考えると現実的かなと思っていた
んですが... int/int->intでは使いこなすのは難しいかなと...

> >CommonLispもそうであったというのに力付けられました(^^;;; それに,
> >Smalltalkもそうだったしたし...
>
>そうなのかあ。CommonLisp と Smalltalk ってがんばってるんだなあ。

CommonLispは知らなかったですけど、Smalltalkは今でもそうですね。ちなみに、

  1/2 + (1/2) -> 1(Integer)

です. CommonLispはどうなんだろう? CommonLisperの人教えてもらえます?

> >1. int/int -> rational だとパフォーマンスが悪いという人がいるが, Rubyで
> >   はそういうことを気にするよりは, 分りやすさを気にすべき. パフォーマン
> >   スを気にする人は、明示的に整除するかto_fすればよい.
>
>rational のパフォーマンスで一番気になるのは、演算を行うたびに gcd 
>の計算をするところですよね。gcd ってのはかなり複雑な計算なんで、
>それが Integer#/ の様な基礎的な位置にある演算子で、特に意識しない
>まま始まってしまうってのがやや気持ち悪いわけです。

でも, gcdって割り算の効率とほとんど同じでないですか? 手元の本だと

除算: O(n * log n * log log n)
gcd:  O(n * (log n)**2 * log log n)

まで効率化できるとなっていました. でも, 約分はgcd求めてから2回除算してい
ますが... 

>ちょっと話それるけど、rational.rb では計算するたびに約分してます
>よね。もしかすると、ある程度分子と分母が大きくなってからとか、表
>示する時に約分する事にするとパフォーマンスが上がるってことありま
>せんかね。

うーん. こういう場合は他の言語の実装を参考にすると... Smalltalkは同じで
す. というか, 同じにつくりました(^^;;; CommonLispとかMathematicaとかはど
うなんだろう?

> >2. int/int -> floatを主張する人も, rationalならまだ納得するはず. という
> >   か, 文句はあってもあきらめるに違いない.
>
>「int/int -> float」派は、この際論外という事で。:-)

(^^;;;

>「int/int -> rational」派にも2つあると思うのですけど、一つは 
>1 / 1 を rational の 1 とするのと、もう一つは 1 / 1 を int の 1 
>とするのと。

ですね. 

>流れからすると、石塚さんと正木さんは後者ですね。後者だとすると例
>えば 1/3 + 2/3 も int の 1 になるわけですね。それはちょっと気持ち
>悪い。

私は一応後者を推していますが、「int/int -> int」派の人も前者なら受入れ可
能だと言うなら、前者でもかまいません.

前者と後者は、原さんも述べているように1長1短がありますし...

(中略)
# ちょっと難しいもので(^^;;;

> >3. matrix.det みたいなものは, 今のメカニズムではどうやっても綺麗に解決しそ
> >   うにない.
>
>これは綺麗に解決しないでいいのではないかなあ。
>
>デフォルトの det は効率が悪くても割り算を利用しない方法を提供して、

うーん. そういう手もあるんでしょうが... 多項式が要素になると割り算してい
るとまずいんですかね?

>さらに要素の状況によっては効率のいい方法をユーザー選べるようにし
>たらいいと思います。結局、効率の問題で不細工になるのは、よくある
>事でしかたがない。本気で効率を考えるユーザーは、自分でアルゴリズ
>ムを選びたいって要求もあるだろうし。

これとは別に、アルゴリズムを選べるようにしたいというニーズはあるかも知れ
ないですね.

> >4. 今回のcomplex#**なんかも根にはこれがある. 
>
>a ** b の話は / とは大分違いますね。** は T op T -> T に拘る必要
>はないですよね。

>環の枠組みで決まる場合、つまり b が非負整数、a が 1、a が -1 で b 
>が分母が奇数の有理数、、、などの場合は自明な値を返すべきだけど、
>それ以外、例えば 2**(-1) の場合は、例外にする(1 / 2 と解釈しない)
>かあるいは 0 にする、というのはありだと思います。これを「不自然」
>という考え方もありますが、不自然なのは 2**(-1) の「値」ではなく、
>整数のカテゴリで 2**(-1) を「させる事」の方なんだ、という考え方を
>します。
>
>(負のfloat) ** float は、require "complex" しても NaN のまま、あ
>るいは例外でいいと思います。それはやはり「本来は複素数」という考
>えをあまりしたくないからです。「本来」って何?と疑問に思います。
>Complex(負のfloat) ** float がそれなりの値を返したとしても、それ
>は本来の値を返したというより、むしろ Complex の仕様に過ぎないと考え
>た方がいいのではないでしょうか。もちろんその仕様はなるべく「自然」
>なものを選ぶべきだけど、そもそも「本来」や「自然」の定義が疑わし
>いわけだから、そんなに拘ることもないと思う訳です。

ここの前の3つの段落意見が発散しているような(^^;;;

>Math.sqrt も同様です。今の所、これの戻り値は Float 固定でいいと思
>います。だって、C のライブラリに依存しているわけでしょう。もっと
>も Float.sqrt などを入れて、Math.sqrt が適宜いい値を返してくれて
>も面白いと思いますが。

こっちはまた別に考えてほうがよいでしょうね.

>ところでこれも別の話だけど、平方根を越えない最大の整数を返す、
>Integer.sqrt ってのもあると便利かなあ。Math.sqrt(2) を 2 乗したと
>き 2 より大きいのか小さいのか、その情報が需要な局面てのもあるから。

Integer.sqrtは高速に計算できそうですね. ビットシフトするだけだから.

>いろんな事言ってますが(^^;、結局私の意見としては、「int/int ->
>rational でがんばってみるのもいいかもしれないが、int/int -> int 
>という現状の仕様のままでも、それはいささかも Ruby の価値を落とし
>てはいない(数学的にも)。Rational は早く C で書き直して組み込み
>にして頂戴、よろしくお願いします。」というものです。

結論としては、rationalでも(型固定なら?)よいよってことですね?

>#どさくさ紛れの要望ですが、Rational(1, 2).inspect は 
>#"Rational(1, 2)" じゃなくて "1/2" にしません?

うーん. (1/2) とカッコ付きなら問題ないかな、複素数は(1+2i)とかかな.

__
..............................石塚 圭樹@日本ラショナルソフトウェア...
----------------------------------->> e-mail: keiju / rational.com <<---