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
相关推荐
vyuvyucd9 分钟前
C++引用:高效编程的别名利器
算法
鱼跃鹰飞34 分钟前
Leetcode1891:割绳子
数据结构·算法
️停云️34 分钟前
【滑动窗口与双指针】不定长滑动窗口
c++·算法·leetcode·剪枝·哈希
charlie11451419137 分钟前
嵌入式现代C++教程: 构造函数优化:初始化列表 vs 成员赋值
开发语言·c++·笔记·学习·嵌入式·现代c++
wjs202439 分钟前
Bootstrap5 消息弹窗
开发语言
资生算法程序员_畅想家_剑魔1 小时前
Kotlin常见技术分享-02-相对于Java 的核心优势-协程
java·开发语言·kotlin
IT=>小脑虎1 小时前
C++零基础衔接进阶知识点【详解版】
开发语言·c++·学习
nbsaas-boot1 小时前
Go vs Java 的三阶段切换路线图
java·开发语言·golang
码农小韩2 小时前
基于Linux的C++学习——指针
linux·开发语言·c++·学习·算法
小L~~~2 小时前
绿盟校招C++研发工程师一面复盘
c++·面试