分数小数変換を改良した
分数から循環小数への変換で、単純な筆算アルゴリズムに変更。
あとテストを改良した。assert_equal(期待する値, 計算式)という形式で呼ぶのがベストかな?
#repeating-decimal.rb require 'rational' class Rational def self.from_rd(s) case s when /^(-?)([0-9]+)$/ return s.to_i.to_r when /^(-?)([0-9]*)\.([0-9]*)$/ return ($1+$2).to_i + ($1+$3).to_i.to_r / 10**$3.size when /^(-?)([0-9]*)\.([0-9]*)\[([0-9]*)\]$/ return ($1+$2).to_i + ( ($1+$3).to_i.to_r + ($1+$4).to_i.to_r / (10**$4.size-1) ) / 10**$3.size else return nil end end def to_rd frac = self; digs = [] mods = [] sign = "" if frac < 0 then sign = "-" frac = -frac end frac -= intg = frac.to_i return sign + intg.to_s if frac == 0 while frac > 0 if ind = mods.index(frac) then return sign + intg.to_s + "." + digs[0...ind].collect{|i| i+?0}.pack("C*") + "[" + digs[ind...digs.size].collect{|i| i+?0}.pack("C*") + "]" end mods.push(frac) frac *= 10 digs.push(frac.to_i) frac -= frac.to_i end return sign + intg.to_s + "." + digs.collect{|i| i+?0}.pack("C*") end end
#!/usr/bin/ruby -Ku #rdtest.rb require "runit/testcase" require "runit/cui/testrunner" require "repeating-decimal" class RDTest < RUNIT::TestCase def test1 assert_equal(Rational(0,1), Rational.from_rd("0")) end def test2 assert_equal(Rational(-0,1), Rational.from_rd("-0")) end def test3 assert_equal(Rational(11,10), Rational.from_rd("1.1")) end def test4 assert_equal(Rational(-11,10), Rational.from_rd("-1.1")) end def test5 assert_equal(Rational(1,3), Rational.from_rd("0.[3]")) end def test6 assert_equal(Rational(-1,3), Rational.from_rd("-0.[3]")) end def test7 assert_equal(Rational(1,6), Rational.from_rd("0.1[6]")) end def test8 assert_equal(Rational(-1,6), Rational.from_rd("-0.1[6]")) end def test9 assert_equal("0", Rational(0,1).to_rd) end def test10 #assert_equal("-0", Rational(-0,1).to_rd) end def test11 assert_equal("1.1", Rational(11,10).to_rd) end def test12 assert_equal("-1.1", Rational(-11,10).to_rd) end def test13 assert_equal("0.[3]", Rational(1,3).to_rd) end def test14 assert_equal("-0.[3]", Rational(-1,3).to_rd) end def test15 assert_equal("0.1[6]", Rational(1,6).to_rd) end def test16 assert_equal("-0.1[6]", Rational(-1,6).to_rd) end def test17 rat = Rational(38657,14272) assert_equal(rat, Rational.from_rd(rat.to_rd)) end def test18 rd = "475.12937462[1836752938]" assert_equal(rd, Rational.from_rd(rd).to_rd) end end RUNIT::CUI::TestRunner.run(RDTest.suite)