分数小数変換をモジュール化してテストを作ってみた

Rubyでテストケース作るのはじめて。

テストケースの書き方がわかりやすくていいね。

変えたこと

  • まず、readline→printというルーチンから、引数→戻り値というルーチンにした。
  • それをRationalのメソッドとして組み込んだ。
  • mathn.rbはシステム全体に影響を与えるので使用しないようにした。
  • テストケースを作った。
#repeating-decimal.rb
require 'rational'

class Integer
  def to_s_digits(base, digits)
    retdigs = Array.new digits
    digits.times do |i|
      retdigs[digits-i-1] = self/10**i%10 + ?0
    end
    return retdigs.pack('C*')
  end
end

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
    sign = ""
    if frac < 0 then
      sign = "-"
      frac = -frac
    end
    frac -= intg = frac.to_i
    if frac == 0 then
      return sign + intg.to_s
      exit
    end
    shft = 0
    while frac.denominator%2 == 0 or frac.denominator%5 == 0
      frac *= 10
      shft += 1
    end
    frac -= fixd = frac.to_i
    #p [intg, fixd, frac, shft]
    if frac == 0 then
      return sign + intg.to_s + '.' + fixd.to_s_digits(10, shft)
      exit
    end
    loop_digs = 1
    loop do
      break if (10**loop_digs-1) % frac.denominator == 0
      loop_digs += 1
    end
    return sign + intg.to_s + '.' + fixd.to_s_digits(10, shft) + '[' + ((10**loop_digs-1)*frac).to_i.to_s_digits(10, loop_digs) + ']'
  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(Rational(0,1).to_rd, "0")
  end

  def test10
    #assert_equal(Rational(-0,1).to_rd, "-0")
  end

  def test11
    assert_equal(Rational(11,10).to_rd, "1.1")
  end

  def test12
    assert_equal(Rational(-11,10).to_rd, "-1.1")
  end

  def test13
    assert_equal(Rational(1,3).to_rd, "0.[3]")
  end

  def test14
    assert_equal(Rational(-1,3).to_rd, "-0.[3]")
  end

  def test15
    assert_equal(Rational(1,6).to_rd, "0.1[6]")
  end

  def test16
    assert_equal(Rational(-1,6).to_rd, "-0.1[6]")
  end
end

RUNIT::CUI::TestRunner.run(RDTest.suite)