1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Float を Rational に変換

1
Last updated at Posted at 2026-04-12

はじめに

Ruby の浮動小数点数型 Float の実体は C の double であり,通常は IEEE 754 / ISO/IEC 60559 に準拠した倍精度浮動小数点数である.INFINITYNaN を除いた有限の値は,分母が 2 の累乗である有理数となる.Ruby には多倍長整数となりうる整数型を分子,分母として保持する有理数型 Rational があるので,有限の Float に対応する値を正確に表現する Rational が必ず存在する.本記事では,その Rational 値を返すメソッド Float#to_r を,基数 Float::RADIX が 2 の場合に限定して再実装してみる.

再実装

class Float
	def to_r
		raise FloatDomainError, self.inspect unless self.finite?
		if RADIX == 2
			s, e = Math.frexp(self)
			if e < MANT_DIG
            	if self < 0.0
					Rational(-Math.ldexp(s, MANT_DIG).to_i, 1<<(MANT_DIG-e))
				else
					Rational(Math.ldexp(s, MANT_DIG).to_i, 1<<(MANT_DIG-e))
				end
			else
				Rational(self.to_i, 1)
			end
		else
			raise NotImplementedError
		end
	end
end

解説

Math.#frexp(f) -> [s, e] は,符号を除いた浮動小数点数を仮数部(浮動小数点数$\in [0.5, 1)$)と指数部(整数)に分解する関数で,$|f|=s\times 2^e$ を満たす.double の仮数部は Float::RADIX$=52+1$ ビットなので,$s\times 2^{53}$ は必ず整数となる.Math.#ldexp(s, e) -> f は,frexp の逆を行う関数なので,frexp から得た s を使って,Math.ldexp(s, 53) は整数を表す浮動小数点数を返す.これを分子,$2^{53-e}$ を分母とすればよい.ここで,分子に符号をつけるのを忘れないようにする.

ただし,e53 より大きいと,$2^{53-e}$ は $1$ より小さい単位分数となってしまう.これは,もとの self がそもそも整数を表している場合に相当する.よって,この場合は,self を整数型に変換したものを分子,1 を分母とすればよい.$e=53$ の場合も,self は整数である.

また,selfINFINITYNaN の場合は,Float#to_i と同様に,FloatDomainError を上げるのがよいだろう.

Float::RADIX が 2 でない場合の実装は省略した.実際の(CRubyにおける) Float#to_r は, C 言語で,(基数が 2 の場合については)これと同等の処理(細かく見るとちょっと違うけど)が書かれている.

おわりに

本記事では,Ruby の Float が有限の場合,それに正確に対応する Rational 値を返すメソッド Float#to_r を、Float::RADIX が 2 の場合に限って再実装した.これを使うと,0.1.to_r #=> (3602879701896397/36028797018963968) などとなり,二進浮動小数点数で正確に表現できない実数の,double における実際の近似値を知ることができ,面白い.分母が $2$ の累乗である有理数は,十進でも有限の小数となるが,その桁数は膨大となる場合があり,分数のほうが少ない桁で正確に表示できる.

参考文献

1
0
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?