桁数を指定せずに大きな数値や精度の高い数値をそのまま文字列にしようとすると、途中で切れたり指数表記になったりする。
float64
の数値をそのまま(非指数表記)でstring
に変換したい。
簡単そうで意外にできなかったので方法を覚書きしておく。
fmtパッケージの変換
fmt.Sprint()
、fmt.Sprintf()
を使う方法を考える。
確認用に同じ変換をするPrint関数を使ってどうなるか見てみる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
big := 100000000.0 //1億 min := 0.00000001 //1億分の1 fmt.Println(big, min) //1e+08 1e-08 fmt.Printf("%f, %f\n", big, min) //100000000.000000, 0.000000 fmt.Printf("%e, %e\n", big, min) //1.000000e+08, 1.000000e-08 fmt.Printf("%g, %g\n", big, min) //1e+08, 1e-08 fmt.Printf("%8.0f, %.8f\n", big, min) //100000000, 0.00000001 |
%f
はno exponent(非指数)、%e
はscientific notation(指数表記)、%g
は多少複雑だけど大体一番短い表記に変換される。
%f
がちょうどよく変換してくれないかと期待したけどデフォルトでは小数点6桁になってしまうらしい(使い物にならない…)。
最後の%8.0f
、%.8f
は期待通りの表示になるけど桁数の指定が必要になる。
strconvパッケージの変換
この問題はstrconv.FormatFloat()
を使う方法で解決できた。
FormatFloat
は基本的に有効桁数を引数に入れる必要がある。
1 2 3 4 |
fmt.Println(strconv.FormatFloat(big, 'f', 0, 64)) //100000000 fmt.Println(strconv.FormatFloat(min, 'f', 8, 64)) //0.00000001 |
しかし -1
を指定することで数値に対応した桁数を文字列にしてくれる。
The special precision -1 uses the smallest number of digits necessary such that ParseFloat will return f exactly.
1 2 |
fmt.Println(strconv.FormatFloat(big, 'f', -1, 64)) fmt.Println(strconv.FormatFloat(min, 'f', -1, 64)) |
これでどんな桁数や精度の数値もそのまま文字列にすることができた。
1 2 3 4 |
fmt.Println(strconv.FormatFloat(10000000000000000000000000, 'f', -1, 64)) fmt.Println(strconv.FormatFloat(0.000000000000000000000001, 'f', -1, 64)) //10000000000000000000000000 //0.000000000000000000000001 |