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数据类型的完整尾数的访问。

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

cpp 复制代码
文件:jsoncpp/src/lib_json/json_writer.cpp

Line 1240

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

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

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

cpp 复制代码
#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,一些其它浮点类型也可能会出错。

cpp 复制代码
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
相关推荐
算法与编程之美1 分钟前
理解Java finalize函数
java·开发语言·jvm·算法
怕什么真理无穷7 分钟前
C++面试4-线程同步
java·c++·面试
lkbhua莱克瓦2410 分钟前
Java基础——常用算法5
java·开发语言·笔记·github
cs麦子19 分钟前
C语言--函数(function)
c语言·开发语言
snowfoootball19 分钟前
python函数及面向过程高级特性
开发语言·python
地平线开发者23 分钟前
LLM 训练基础概念与流程简介
算法·自动驾驶
是苏浙24 分钟前
零基础入门C语言之C语言实现数据结构之顺序表
c语言·开发语言·数据结构
点云SLAM28 分钟前
弱纹理图像特征匹配算法推荐汇总
人工智能·深度学习·算法·计算机视觉·机器人·slam·弱纹理图像特征匹配
星释28 分钟前
Rust 练习册 :Matching Brackets与栈数据结构
数据结构·算法·rust
地平线开发者29 分钟前
Camsys 时间戳信息简介
算法·自动驾驶