浮動小数点数の16進数表記を得る(SW)
前回
Float計算回路のVerilog-HDL実装について -その1
4/26 シミュレーション結果を追記
5/17 負の数のバグを修正
今回の内容
32bit float (single) が正しい値なのか
float値と16進表記値を相互変換するツールを作成する
cgo 使います
偉大な先駆者様(参考文献)
コード全体
今回作成したコード
check.go
package main
/*
union {float f; unsigned i;} uv;
int f2b(float inp) {
uv.f = inp;
return uv.i;
}
float b2f(unsigned inp) {
uv.i = inp;
return uv.f;
}
*/
import "C"
import (
"fmt"
"os"
"strconv"
)
func main() {
if os.Args[1] == "f" {
fmt.Println("float -> hx")
fv, _ := strconv.ParseFloat(os.Args[2], 32)
f2h(float32(fv))
} else if os.Args[1] == "h" {
fmt.Println("hx -> float")
hv, _ := strconv.ParseUint(os.Args[2], 16, 32)
h2f(uint(hv))
}
}
func h2f(inp uint) {
float := float32(C.b2f(_Ctype_uint(inp)))
fmt.Println(float)
}
func f2h(inp float32) {
bits := int(C.f2b(_Ctype_float(inp)))
fmt.Printf("Hex:%08X\n", bits)
fmt.Printf("Exp:%02X\n", bits >> 23 & 0xFF)
fmt.Printf("Fra:%X\n", bits & 0x7FFFFF)
}
共用体で値をコンバートしている
特殊なことはしていないのでCでも実装できると思う
(むしろGoだけで実装できるのか?)
テスト
$ go run check.go f 7.25
float -> hx
Hex:40E80000
Exp:81
Fra:680000
Exp のバイアス値 127 は 7F であるため
+2 された 81 が指数部の値となっている
また、680000 = 110 1000 0 0 0 0 なので
7.25 = 111.01 = 680000 x 2^2 となっていることがわかる
$ go run check.go h 40E80000
hx -> float
7.25
正しく戻せていることがわかる
シミュレーション結果の検証
7.25 + 11.625
7.25 + 11.625 = 18.875 \\
-> 40E8\_0000 + 413A\_0000 = 4197\_0000\\
あってるっぽい
12.345 + 3.1415926
12.345 + 3.1415926 = 15.4865926\\
-> 4145\_851F + 4049\_0FDA = 4177\_C915
あってるっぽい