Go Protobuf 精度小数

Mat*_* Mc 10 go protocol-buffers arbitrary-precision

如果我想传输任意精度的十进制值,在我的 protobuf 定义文件中使用的正确标量类型是什么?

我在 Go 代码中使用shopspring/decimal而不是 float64 来防止数学错误。在编写我的 protobuf 文件以通过 gRPC 传输这些值时,我可以使用:

传统智慧教会我在货币应用程序中避开浮动,但我可能过于小心,因为它是序列化的一个点。

CAF*_*FxX 3

如果您确实需要任意精度,恐怕现在没有正确的答案。有https://github.com/protocolbuffers/protobuf/issues/4406开放,但似乎不是很活跃。如果没有内置支持,您确实需要手动执行序列化,然后使用 或stringbytes存储结果。string在和 之间使用哪一种bytes可能取决于您是否需要跨平台/跨库兼容性:如果您需要兼容性,请使用string阅读器中适当的任意精度类型来使用和解析字符串中的十进制表示形式;如果您不需要它并且要使用相同的 cpu 架构和库读取数据,您可能只需使用该库 ( MarshalBinary/ UnmarshalBinary) 提供的二进制序列化并使用bytes.

另一方面,如果您只需要以适当的精度发送货币值,而不需要任意的精度,您可能只需使用sint64/uint64并使用适当的单位(这些通常称为定点数)。举个例子,如果您需要用 4 位小数位表示美元的货币值,则您的单位将是美元的 1/10000,例如,该值1表示 $0.0001,该值19900表示 $1.99,-500000表示 $-50,等等在。使用这样的单位,您可以表示范围 $-922,337,203,685,477.5808 到 $922,337,203,685,477.5807 - 这可能足以满足大多数用途。您仍然需要手动执行缩放,但它应该相当简单且便携。考虑到上面的范围,我建议sint64最好使用 using ,因为它还允许您表示负值;uint64仅当您需要额外的正范围且不需要负值时才应考虑。

或者,如果您不介意导入另一个包,您可能需要查看https://github.com/googleapis/googleapis/blob/master/google/type/money.protohttps://github。 com/googleapis/googleapis/blob/master/google/type/decimal.proto(顺便实现了与上述两个模型非常相似的东西),以及https://pkg.go.dev/github 上的相关实用函数。 com/googleapis/go-type-adapters/适配器

顺便说一句,您几乎不应该使用浮点数来表示货币值,这是完全正确的。