循環小数を分数に
「循環小数を分数に直す@Ruby - 簡潔なQ」が面白そうだったのでやってみた。
require "rational" def period source # [整数部, 小数部, 循環小数部]を取得する正規表現 matches = source.match(/\A(-?\d+)(?:\.(\d*)(?:\[(\d+)\])?)?\Z/) raise ArgumentError.new("#.###[###]") unless matches # 整数部のみならそのまま返却 return matches[1].to_i unless matches[2] # 整数部と小数部の計算 numerator = (matches[1]+matches[2]).to_i denominator = 10**matches[2].size # 循環小数部の計算 if matches[3] period_factor = 10**matches[3].size-1 numerator = numerator*period_factor + matches[3].to_i denominator = denominator*period_factor end return numerator.quo(denominator) end
同じことやってるのに行数めっちゃ増えてる!
テスト
上のコードを「period.rb」として保存。
require "test/unit" require "period" class TestPeriod < Test::Unit::TestCase def test_integer assert_equal 1, period( "1") assert_equal -1, period("-1") assert_equal 1, period( "1.") end def test_integer_fraction assert_equal 1, period( "1.0") assert_equal -1, period("-1.0") end def test_fraction assert_equal 11.quo(10), period( "1.1") assert_equal 11.quo(10), period( "1.100") assert_equal 1111.quo(1000), period( "1.111") end def test_period assert_equal 10.quo(9), period( "1.[1]") assert_equal 10.quo(9), period( "1.[11]") assert_equal 10.quo(9), period( "1.[111]") assert_equal 1233.quo(999), period( "1.[234]") assert_equal 111.quo(90), period( "1.2[3]") assert_equal 1111.quo(90), period( "12.3[4]") end def test_raised assert_raise(ArgumentError){ period("1.[]") } end end
One Assertion Per Testはー?