Help us understand the problem. What is going on with this article?

GoとMongoDBとProtocol Buffersでの小数の扱い

MongoDB上でNumberDecimal()を使いdecimalで小数を格納していたのだが、それを"mongo-go-driver"を介してDecode()する時に、cannot decode 128-bit decimal into a float32 or float64 typeとエラーが出て困ったので、各々の小数周りの仕様を調べた。

それぞれの小数周りの仕様へのリンク集としても役立つはず。

Go

Go上で小数に対応する型は、Numeric typesの仕様によると、float32float64のよう。

Protocol Buffers

"proto3"のLanguage GuideにあるScalar Values Type表によると、proto上での小数表記はfloatdooubleで、それぞれGo上ではfloat => float32double => float64となるらしい。

MongoDB

MongoDB上では、schema定義のドキュメント曰く、doubledecimalが存在する。これはBson Typeにあたるので、Bsonの仕様書を見てみると、どうやら64bitで表現されるのがdoubleであり、128bitで表現されるのがdecimal (decimal128)であることがわかる。

MongoDBとGoの間でやり取りするには、基本的に"mongo-go-driver"を使うことになると思うが、その中の"go.mongodb.org/mongo-driver/bson"についての箇所を見ると、BSONのdoublefloat64に、128-bit decimalprimitive.Decimal128にエンコードされることがわかる。

"mongo-go-driver"でのDecimal128の扱いを読んでみると、BigInt()big.Intとexponential部分を返すメソッドはあるようだが、Decimal128をGo標準のfloat64などに変換するメソッドはないことがわかる。

結論 string 最強

今回は、計算したい要件がなく、ただMongoDBから取得したデータをGoを介してProtocol Buffer経由でクライアントに送りたいだけだったので、結局stringにすることにした。他にも、別にMongoDBに入れるのにdecimalであることにこだわりがなければ、doubleを使用することでGo上ではfloat64として扱うことができるので、問題は発生しない。

もし計算したいなら、Decimal128stringにして、それをさらにfloat64などにするのが良いのか、BigInt()を使って頑張れるのか("math/big"Floatに頑張って変換できれば良いのだが)、Decimal128のまま計算する方法があるのかはわかっていない。

何れにしても、小数周りはどの言語でも辛いんだなぁと思った。
(jsだけじゃなかった。。。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした