Skip to content

Instantly share code, notes, and snippets.

@atton
Last active December 12, 2015 02:38
Show Gist options
  • Save atton/4700346 to your computer and use it in GitHub Desktop.
Save atton/4700346 to your computer and use it in GitHub Desktop.
VLSIなアレ
# vim:set fileencoding=utf-8:
Point = 5 # 固定小数点の位置
def convert_2_to_10 bit_array
# 2進数複素数列から10進数複素数へ変換。
# bit_array は [String] を想定。Stringはsize1。
real_sign, real = convert_sign_2(bit_array[0..15])
imaginary_sign, imaginary = convert_sign_2(bit_array[16..32])
real = _convert_2_to_10(real)
imaginary = _convert_2_to_10(imaginary)
real_sign + real.to_s + ", " + imaginary_sign + imaginary.to_s
end
def _convert_2_to_10 bit_array
# 実部虚部関係無く、16ビット長の2進列を10進に変換する
# 符号は考慮しない
weight_array = 0.upto(15).map{|a|2**(Point-a)}
bit_array = bit_array.zip(weight_array)
bit_array = bit_array.map{|(a,b)| a.to_f * b.to_f}.inject(:+)
end
def convert_sign_2 bit_array
# 2進数列を符号と絶対値の2進列に変換する
# [符号, 絶対値配列] を返す
sign = "+"
if bit_array[0] == "1"
# 符号ビットが負なら反転
sign = "-"
bit_array = bit_array.map{|a| a == "1" ? "0" : "1"}
# プラス1する
carry = "1"
bit_array = bit_array.reverse.map do |a|
case [a, carry]
when ["0", "1"]
carry = "0" ; "1"
when ["1", "1"]
carry = "1" ; "0"
else
# 桁上げ無しの時。そのまま
a
end
end
bit_array.reverse!
end
[sign, bit_array]
end
def convert_10_to_2 complex_str
# 10進数複素数から2進数複素数列へ変換
real, imaginary = complex_str.split(",").map{|a|a.gsub(" ","")}
real = _convert_10_to_2(convert_sign_10(real))
imaginary = _convert_10_to_2(convert_sign_10(imaginary))
real.join + imaginary.join
end
def _convert_10_to_2 sign_and_str
# "符号 10進数" から2進数列へ変換する
sign = sign_and_str.first
value = sign_and_str.last.to_f
weight_array = 0.upto(15).map{|a|2**(Point-a)}
bit_array = []
# 絶対値から2進列を作る
weight_array.each do |w|
if value >= w
value -= w
bit_array << "1"
else
bit_array << "0"
end
end
__convert_10_to_2(sign, bit_array)
end
def __convert_10_to_2 sign, bit_array
# 符号と2進数列から2進数を返す (必要に応じて2の補数を取る)
# convert_sign_2 を少し流用(桁上げがしたかった)
(sign == "-") ? bit_array[0] = "1" : bit_array[0] = "0"
bit_array = convert_sign_2(bit_array).last
(sign == "-") ? bit_array[0] = "1" : bit_array[0] = "0"
bit_array
end
def convert_sign_10 str
# 符号と絶対値に分ける
if str.include?("-")
return ["-", str.gsub("-","")]
else
return ["+", str.gsub("+","")]
end
end
# puts convert_2_to_10("00000010000000001111111000000000".chars.to_a)
# puts convert_2_to_10("11111110000000000000001000000000".chars.to_a)
# puts convert_10_to_2("0.5,-0.5")
# puts convert_10_to_2("-0.5,0.5")
# puts convert_10_to_2(convert_2_to_10("00000010000000001111111000000000".chars.to_a))
# puts convert_10_to_2(convert_2_to_10("11111110000000000000001000000000".chars.to_a))
# puts convert_2_to_10(convert_10_to_2("0.5,-0.5").chars.to_a)
# puts convert_2_to_10(convert_10_to_2("-0.5,0.5").chars.to_a)
DATA.each do |l|
puts l
end
print "> "
while data = gets
data = data.chomp
if data.size == 32 && data.chars.all?{|d| d == "0" || d == "1"}
# 2進数列とみなした時
puts convert_2_to_10(data.chars.to_a)
elsif data.include?(",") && data.split(",").size == 2
puts convert_10_to_2(data)
else
puts "たぶんフォーマット違います。"
end
print "> "
end
__END__
VLSIな固定小数の 2進数 <-> 10進数相互変換。
2進数は 0と1のみの32個を食わせればOK.
10進数は実部と虚部を "," 区切りで食わせればOK.
たぶん動く。なんかミスってたら残念ということで。
範囲外に出たときのチェックとかはしてないのでその辺何か問題ありそう。
えーっと、ご利用は自己責任で、ってことで。
例はこんな感じ。
> -0.5,0.5
> 00000010000000001111111000000000
convert.rb をダウンロードして
ruby convert.rb
くらいで動くはず。動かなくても泣かない。バグってても泣かない。
とりあえずいわゆる自己責任ってやつで。
既知のバグ
・10進数 -> 2進数変換の時に -0 とかを入れると変な値が出る
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment