jsoncpp库输出浮点型值精度错误

可以看到图中71.21的值经过jsoncpp转换后变成了71.20999999999999

这是因为 21/100 没有精确的浮点表示,默认情况下,我们使用17位数字,因为这是将double的任何值明确表示为字符串所需的数字。此17==DBL_DECIMAL_DIG==std::numeric_limits<double>::max_digist10。以这种精度打印可以保证任何双值都可以在打印和解析时存活下来,而不会失真。这与15==DBL_DIG==std::numeric_limits<double>::digitals10不同,后者是可以在不失真的情况下从字符串解析到double并返回的最大位数。因此,17的默认值是一种折衷。我们选择了足够多的数字来完美地表示每一个可能的双精度值。不过,这不是我想要的。所以只需要15位数字的精度,因为15位数字可以在不失真的情况下解析和重新打印,但这会牺牲对double数据类型的完整尾数的访问。

如果您需要自定义输出并使用自定义配置的编写器,有一种方法可以设置精度。

文件:jsoncpp/src/lib_json/json_writer.cpp

Line 1240

 (*settings)["precision"] = 17; 

将17修改为15即可正常输出71.21

以下代码可以看出计算机对不同位数精度的不同输出:

#include <iostream>
#include <iomanip>
#include <string>
#include <cmath>

constexpr double inf = std::numeric_limits<double>::infinity();

void dumpTable(double x) {
    int maxPrecision = 25;
    double xPlusEpsilon = std::nextafter(x, inf);
    for (int p = 0; p < maxPrecision; ++p) {
        std::cout << "p=" << std::setw(3) << p;
        for (auto f : {x, xPlusEpsilon}) {
            std::cout
                << ", "
                << std::setprecision(p)
                << std::defaultfloat
                << std::setw(maxPrecision + 5)
                << f;
        }
        std::cout << std::endl;
    }
}

int main() {
    dumpTable(71.21);
    return 0;
}

可以从下面看出16位时,输出71.21则会出错,当然不止72.21,一些其它浮点类型也可能会出错。 

p=  0,                          7e+01,                          7e+01
p=  1,                          7e+01,                          7e+01
p=  2,                             71,                             71
p=  3,                           71.2,                           71.2
p=  4,                          71.21,                          71.21
p=  5,                          71.21,                          71.21
p=  6,                          71.21,                          71.21
p=  7,                          71.21,                          71.21
p=  8,                          71.21,                          71.21
p=  9,                          71.21,                          71.21
p= 10,                          71.21,                          71.21
p= 11,                          71.21,                          71.21
p= 12,                          71.21,                          71.21
p= 13,                          71.21,                          71.21
p= 14,                          71.21,                          71.21
p= 15,                          71.21,                          71.21
p= 16,              71.20999999999999,              71.21000000000001
p= 17,             71.209999999999994,             71.210000000000008
p= 18,            71.2099999999999937,             71.210000000000008
p= 19,           71.20999999999999375,           71.21000000000000796
p= 20,          71.209999999999993747,          71.210000000000007958
p= 21,         71.2099999999999937472,         71.2100000000000079581
p= 22,        71.20999999999999374722,        71.21000000000000795808
p= 23,       71.209999999999993747224,       71.210000000000007958079
p= 24,      71.2099999999999937472239,      71.2100000000000079580786

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

美丽的欣情

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值