在我的项目中,我使用 QJsonDocument::fromJson()
从一个 json 文件中读取。这很好用,但是当我尝试使用 toJson()
将 QJsonDocument
写回文件时,一些 double 已经搞砸了精度。
例如,在具有 QJsonValue
且 double 值为 0.15
的文档上调用 toJson()
将保存为文件 0.14999999999999999
。我不想要这个。
这是因为 Qt 源文件 qjsonwriter.cpp 第 126 行 (Qt 5.6.2)
读取:
json += QByteArray::number(d, 'g', std::numeric_limits<double>::digits10 + 2); // ::digits10 is 15
最后的 +2 把我搞得一团糟。如果对 QByteArray::number()
的相同调用的精度为 15(而不是 17),则结果完全符合我的需要...0.15
。
我理解浮点精度的格式如何导致 double 在它可以表示的范围内受到限制。但是,如果我将精度限制为 15 而不是 17,这会产生匹配输入 double 的效果,这正是我想要的。
我该如何解决这个问题?
显然...我可以编写自己的 Json 解析器,但那是最后的手段。显然我可以编辑 Qt 源代码,但是我的软件已经部署在每个人的安装目录中的 Qt5Core.dll 中,并且我的更新程序并非设计用于更新任何 dll。所以我无法编辑 Qt 源代码。
希望有人能解决这个问题:)
最佳答案
this has the effect of matching the input double precision, which I want.
这个请求没有多大意义。 double 不包含任何关于其精度的信息——它只包含一个值。 0.15、0.1500 和 0.14999999999999999 是完全相同的 double 值,JSON 编写器无法首先知道它是如何从文件中读取的(如果它是从文件中读取的)。
一般来说,您不能像您建议的那样要求最大 15 位精度,因为根据特定值,精确的 double->text->double 往返需要最多 17 位,因此您会编写不正确的四舍五入值.然而,一些 JSON 作者所做的是用读取相同的双反所需的最小小数位数来编写数字。除非您像许多人那样做从 15 到 17 的循环,以如此精确的方式写下数字,然后解析它并查看它是否返回为完全相同的 double 值,否则要正确地进行数字计算远非易事。虽然这会生成“更好”(和更小)的输出,但它需要更多工作并减慢 JSON 写入速度,所以这可能是 Qt 不这样做的原因。
不过,您可以编写自己的 JSON 代码并拥有此功能,对于一个简单的递归实现,我预计大约有 15 行代码。
话虽这么说,但如果您想精确匹配您的输入,这也救不了您——因为这根本不可能。
关于c++ - QJsonDocument::toJson() 不正确的 double ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51257690/