けいじゅ@日本ラショナルソフトウェアです. In [ruby-list :07035 ] the message: "[ruby-list:7035] Re: modulo ", on Mar/10 05:27(JST) toyofuku / juice.or.jp writes: > 豊福@パパイヤです。 > mathn.rb で / を再定義している路線をねらったん >ですが。 うーん. あれは, / だけですからね... ほとんどの場合, rubyも問題なく動作 するでしょう(^^''' >> # いや, 無理があるというのと違うかな, 目的が剰余系なrubyを作りたいとい >> # うなら別ですが... > > mathn.rb で分数電卓の気分で使えたように剰余系 >電卓の気分で使えるようなものができないかというのが >目的です。 うーん. なるほど.... そうするとかなりうらわざを使う必要が出てきますね... こんなのはどうでしょう? -- $mod = 0 def modulo(n) $mod = n.abs end class Fixnum alias no_pl + alias no_mn - alias no_ml * alias no_dv / def mo_pl (other); super; end def mo_mu (other); super; end def mo_ml (other); super; end def mo_dv (other); super; end alias + mo_pl alias - mo_mu alias * mo_ml alias / mo_dv def mo_divmod(other) normal do x = self / other y = self - x * other return x, y end end alias divmod mo_divmod end class Bignum alias no_pl + alias no_mn - alias no_ml * alias no_dv / def mo_pl (other); super; end def mo_mu (other); super; end def mo_ml (other); super; end def mo_dv (other); super; end alias + mo_pl alias - mo_mu alias * mo_ml alias / mo_dv def mo_divmod(other) normal do x = self / other y = self - x * other #y = self.mn(x.ml(other)) return x, y end end alias divmod mo_divmod end class Integer def normal for t in [Fixnum, Bignum] eval %Q[ class #{t} alias + no_pl alias - no_mn alias * no_ml alias / no_dv end ], TOPLEVEL_BINDING end begin return yield ensure for t in [Fixnum, Bignum] eval %Q[ class #{t} alias + mo_pl alias - mo_mn alias * mo_ml alias / mo_dv end ], TOPLEVEL_BINDING end end end def mod if ($mod == 0) return self else void, x = self.divmod($mod) normal{x = x + $mod} if (x < 0) return x end end def inv x = self y = $mod klist = [] void, a = x.divmod(y) normal{a = a + y} if (a < 0) b = y while b != 0 k, a = a.divmod(b) klist.push(k) a, b = b, a end klist.pop normal do a, b = 1, 0 while (k = klist.pop) a, b = k * a + b, a end if (x * b - y * a < 0) b = y - b end return b end end def mo_pl(other) normal{self + other}.mod end def mo_mn(other) normal{self - other}.mod end def mo_ml(other) normal{self + other}.mod end def mo_dv(other) normal do if ($mod == 0) self / other else (self * other.inv).mod end end end end --- # 大体動作しますがバグ付きです(^^;;; # あと, ruby-1.1b9でないと動作しません. 味噌はイテレータnormalです. normal{exp} の中では通常の計算が可能になります. # ただし, 中でaliasしているのでマルチスレッド対応ではありません. でも, これではforの問題は解決していませんので modulo(n) {exp} でそのイテレータの中だけ剰余系にするというほうが良いかも知れません. そうすると, 1. $modの様な大域変数なしにできる 2. forも無理なく使えると思う def fib(n); a, b = 1, 1; for i in 1..n do; modulo(3) {print "#{b} "; a, b = (a+b)*1, a} end; print "\n"; end; まあ, プログラムの中にmoduloイテレータが入ってしまいますが... >> ># 剰余系での演算 >> ># 合成数のケースはちょっと面倒なので後まわし >> 合成数って何でしたっけ? > > えっ・・・、素数でも1でもない自然数のことです・・・。 >前に書いたプログラムは 4 / 6 mod 10 みたいなやつに >対応してません。 そうでしたっけ? すっかり忘れたなあ... __ ................................石塚 圭樹@日本ラショナルソフトェア... ----------------------------------->> e-mail: keiju / rational.com <<---