実数を分数に変換する処理

システム内部で数値を分数で扱っているものがあり、一部の計算でどうしても実数を分数に変換しなければならないケースがあったため、実数を分数にするアルゴリズムが無いか考えてみました。

もっとも簡単な方法は、小数桁数nの10のべき乗(10^n)を分母にする方法ですが、桁数の少ない有限小数(0.125とか)ならきれいに分数に変換できます。しかし、分母とする値に限界があるため、桁数の多い有限小数や無限小数の場合は、足切りした桁数で誤差が発生してしまいます。
また、実数は浮動小数点(Single, Double)で扱うことが多いので、指数部と仮数部から求めた小数を表すビット数nの2のべき乗(2^n)を分母とし、浮動小数点で表せる範囲で精度を高める方法も考えましたが、浮動小数点で正確に表せない実数(0.1など)がうまく表せなくなる問題があります。

実数を分数にするためには、実数に何を掛ければ整数となるかの最小値を求めます。
例えば、0.5 の場合は 0.5 / 1 = (0.5 × 2) / (1 × 2) = 1 / 2 の計算のように、分子と分母に掛けた値「2」が求まれば良いことになります。

実数を整数とする値は、単純に「1 ÷ 小数部」で求められますが、0.8 の場合は 1 ÷ 0.8 = 1.25と求めた値が実数となる場合があります。求めた値を整数にするため、同様の計算を繰り返すことで、実数を整数とする値を求めることができます。

○実数が0.8の場合

(0.8)  ⇒ 1 ÷ 0.8 = 1.25  … 値に小数がある場合はもう一度
(1.25) ⇒ 1 ÷ 0.25 = 4

求められた結果は 1.25 × 4 = 5
実数の分子/分母にあてはめると、
(0.8 × 5) / (1 × 5)  =  4 / 5

ちなみに、計算過程(無限小数)で誤差が含まれることがあるため、求めた値に小数がなくなったことが正しく判断できない場合あります。このため、求められた結果が実数と一致するかで処理の終了を判断します。

〇実数が0.3の場合

(0.3) ⇒ 1 ÷ 0.3 = 1.333…
(1.333…) ⇒ 1 ÷ 0.333… ≒ 3

求められた結果は  1.333… × 3 = 10
実数の分子/分母にあてはめると、
(0.3 × 10) / (1 × 10)  =  3 / 10

上記の処理を組み込んだ分数型(Fraction構造体)を.NETのクラスライブラリにて公開していますので、試してみたい方はこちらからダウンロードしてください。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする