3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Rubyで固定小数点数を2進リテラル(っぽく)書けるようにした(メタプロもあるよ!)

Last updated at Posted at 2017-09-30

背景・動機など

 ここ最近 こちらのQiita記事 を参考にしつつ FPGA に16ビット固定小数演算器を実装しようと日々奮闘しておりまして、FPGA やってるとビット単位で信号を扱うことになるので、当然2進数表記が重要になってきます。

 Verilog のシミュレーションを Verilator の生成コードを利用しつつ、Ruby から使えるようにした話 は先日公開させていただきました。

 固定にしろ浮動にしろ、何ビットで計算するにしろ、小数点つきの数を2進リテラルを Ruby でうまく表現できないものかなー、と思っておりました。ちなみに 0b010111.101 みたいな表記だと Syntax Error になります。うむむ。

小数表記をメタプログラミングで

 で、1日後、「あ、method_missing 使って 0b011.b101 って書けるようにすればいいんじゃね?」と思いつきました。メタプログラミングの一種ですね。Ruby の文法上、数字で始まるメソッドは定義できませんから、一文字以上のアルファベットはどうしても必要になります。

 例えば、こんなふうに書けます。

> 0b01.b01      # => (5/4)
> -0b01.b01     # => (-5/4) 

 ご覧の通り、内部では Rational として扱っています。私の目的にはあまり必要ではありませんが、任意精度の計算にも対応したかったので。

2進小数表記「へ」の変換

 2進固定小数の表記はこれでいいとして、任意の数を2進固定小数表記「に」変換するのはどうするか。10進→2進変換はぐぐれば山と出てきますが、いずれも正の整数が前提。。。orz

 でまあ数日悩んでおったのですが、なんとか形になりました。整数部と小数部の桁数を分けて書く [Q format] (https://en.wikipedia.org/wiki/Q_(number_format))というのを使います。

> 1.25.q(4,4, true)      # => "0001.0100" 
> -1.25.q(4,4, true)     # => "1110.1100"

 qメソッドに渡す引数は順に

  • 整数部の桁数
  • 小数部の桁数
  • 小数点を表示するか否かのフラグ。デフォルトは false 。

 です。有理数にも適用できます。

> (11/8r).q(4,4,true)    # => "0001.0110" 
> (-11/8r).q(4,4,true)   # => "1110.1010" 

入手は gist で

 今回は gist にあげてみました。 今回もRuby スクリプト1個なので、コードコピペしてもいいですし、git clone するなら

$ git clone https://gist.github.com/sin00b/c3cd8688294d9b41b0e1f98cce391375 hoge

としていただければいいです。

 コードみていただければわかりますが、負数表記に変換するのに String#tr で置換しています。理屈としてはこれでもできるけど、ちょっとなぁって思ってます。

3
2
0

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
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?