json - 解组 json 以浮动。为什么需要 float64?
问题描述
我注意到 go unmarshals json floats 的方式有一些奇怪的行为。一些数字,但不是全部,拒绝正确解组。解决这个问题就像在目标变量中使用 float64 而不是 float32 一样简单,但是对于我的生活,我找不到一个很好的理由为什么会出现这种情况。
这是演示该问题的代码:
package main
import (
"encoding/json"
"fmt"
. "github.com/shopspring/decimal"
)
func main() {
bytes, _ := json.Marshal(369.1368) // not every number is broken, but this one is
fmt.Println("bytes", string(bytes))
var f32 float32
json.Unmarshal(bytes, &f32)
fmt.Printf("f32 %f\n", f32) // adds an extra 0.00001 to the number
var d Decimal
json.Unmarshal(bytes, &d)
fmt.Printf("d %s\n", d) // 3rd party packages work
// naw, you can just float64
var f64 float64
json.Unmarshal(bytes, &f64)
fmt.Printf("f64 %f\n", f64) // float64 works
}
不需要 float64 来准确表示我的示例编号,那么这里为什么需要呢?
去游乐场链接: https: //play.golang.org/p/tHkonQtZoCt
解决方案
您的断言是错误的:369.1368
不能完全用or来 表示。float32
float64
最接近的float32
值是 (近似) 369.136810302734375
,四舍五入到369.13681
哪个是您的额外数字的来源。最接近的float64
值是 (approximately) 369.13679999999999382
,对于您的目的来说,它会更好地舍入。
(当然,如果你将其中任何一个四舍五入到小数点后四位,你就会得到你期望的数字。)
表示是准确的Decimal
:没有舍入误差。
JSON 传输和接收以十进制表示的浮点值,但在各种语言的实际实现中,然后以不同的方式对这些数字进行编码。根据您通过 JSON 与之交谈的实体类型,编码和解码 viaDecimal
可以完全按照您的意愿保留数字,但请注意,用 C++ 或 Python 编写的程序可能会将您的数字解码为不同的浮点数点精度并引入各种舍入误差。
这个 Go Playground 示例使用了新添加的%x
格式,并向您展示了数字是如何在内部存储的:
作为 float32 = 369.13681030273437500 (float32),实际上是 12095875p-15 或 0x1.712306p+08
和:
作为 float64 = 369.13679999999999382 (float64),实际上是 6493923261440380p-44 或 0x1.712305532617cp+08
也就是说,数字 369。无论在内部以二进制表示。它在 2 8 = 256 和 2 9 = 512 之间。在二进制中,它是 1 256、没有 128、1 64、1 32、1 16、没有 8、没有 4、没有 2 和 1 1:1.01110001 something x 2 8 . 格式以(1 . 0111 0010)开头,以%b
一种方式表达,而以另%x
一种方式表达。%x
1.72
请参阅浮点数学是否损坏?(作为评论中链接的 jub0bs )了解更多信息。
推荐阅读
- android - Android Studio 我如何在所有屏幕上显示图像大小
- amazon-s3 - 版本控制如何在 Amazon Cloudfront 上工作?
- angular - 使用 trackBy 仅在 ngFor 中对象的特定属性更改时渲染 DOM
- c++ - 宽度,高度和线条大小之间的AVFrame混淆
- image - PyTorch:将多条记录包装在一个文件中?
- java - 在线程中如何返回上一个活动
- apache-spark - Kubernetes WatchConnectionManager:执行失败:HTTP 403
- multithreading - 你可以为线程指定一个非静态的生命周期吗?
- .net - 如何在.net core web 中将 url 设置为 webapi?
- java - STOMP 目标 url 与端点 url