gpt4 book ai didi

c++ - Jsoncpp 错误地写入浮点值

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:34:14 26 4
gpt4 key购买 nike

我正在使用 jsoncpp 读取 JSON 文件。当我写回文件时,我的浮点值略有偏差。为了进行测试,我决定将文件解析为 Json::Value,然后将该值写回到文件中。我希望它看起来一样,但浮点值不同。

例子:

"Parameters":
{
"MinXValue": 0.1,
"MaxXValue": 0.15,
"MinYValue": 0.25,
"MaxYValue": 1.1,
"MinObjectSizeValue": 1
}

写成:

"Parameters":
{
"MinXValue": 0.10000000000000001,
"MaxXValue": 0.14999999999999999,
"MinYValue": 0.25,
"MaxYValue": 1.1000000238418579,
"MinObjectSizeValue": 1
}

您可能会注意到 0.25 没有变化,尽管所有其他 float 都发生了变化。知道这里发生了什么吗?

最佳答案

其实是 float 解析/打印实现的问题。虽然 float 只能精确表示一些十进制数(0.25 是 ~2^64 之一),但需要将字符串表示解析为最接近的二进制表示。打印 float 时,还需要打印(最好是最短的)可以还原为二进制表示的字符串表示。

我承认我没有调查 JsonCPP 看是否有解决方案。但因为我是 RapidJSON 的作者,我试着看看 RapidJSON 如何执行此操作:

const char json[] = 
"{"
"\"MinXValue\": 0.1,"
"\"MaxXValue\": 0.15,"
"\"MinYValue\": 0.25,"
"\"MaxYValue\": 1.1,"
"\"MinObjectSizeValue\": 1"
"}";

using namespace rapidjson;

Document d;
d.Parse(json);

StringBuffer sb;
PrettyWriter<StringBuffer> writer(sb);
d.Accept(writer);

std::cout << sb.GetString();

结果:

{
"MinXValue": 0.1,
"MaxXValue": 0.15,
"MinYValue": 0.25,
"MaxYValue": 1.1,
"MinObjectSizeValue": 1
}

RapidJSON 在内部实现了解析和打印算法。普通精度解析将有最多 3 个 ULP 错误,但是使用全精度解析标志 (kParseFullPrecisionFlag) 它总是可以解析到最接近的表示。打印部分实现了Grisu2算法。它确实总是会生成准确的结果,并且超过 99% 的时间是最短的(最优的)。

其实用strtod()sprintf(..., "%.17g", ...)也可以解决这个问题。但它们在当前的 C/C++ 标准库中要慢得多。比如我做了一个benchmark用于打印 double。因此,在 RapidJSON 中,我们实现了自己优化的仅 header 解决方案。

关于c++ - Jsoncpp 错误地写入浮点值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29832984/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com