You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用nlohmann::json库读取JSON浮点数时精度偏差的解决方案咨询

解决nlohmann::json读取浮点数得到近似值的问题

这其实是二进制浮点数的精度限制导致的常见问题,和nlohmann::json库本身无关,也不是你的代码逻辑错误~

问题根源

float是32位单精度浮点数,它的有效数字只有6-7位左右。而86700.2这个数:

  • 整数部分已经占了5位,剩下的有效位数不足以精确表示小数部分的0.2(因为0.2无法用二进制有限小数来表示,只能用一个无限接近的近似值)。
  • 不管你是从JSON数值直接转float,还是先转字符串再用std::stof转float,最终都会落到这个精度限制上,所以得到的都是86700.2031这个最接近的float近似值。

解决方案

根据你的需求,有几种可行的处理方式:

1. 改用double类型存储(最推荐)

double是64位双精度浮点数,有效数字能达到15-17位,足以精确表示86700.2的近似值(误差小到几乎可以忽略)。修改代码如下:

using json = nlohmann::json;
std::string config_path = "C:/config/default.json";
std::ifstream config_file(config_path);
json config = json::parse(config_file);
double test = config["test"]; 
// 输出时如果设置合适的精度,会显示为86700.2
std::cout << std::fixed << std::setprecision(1) << test << std::endl;

2. 保留float,但格式化输出

如果必须使用float类型,可以在输出的时候通过格式化控制小数位数,让结果显示为你预期的86700.2

#include <iomanip> // 需要包含这个头文件

float test = config["test"];
std::cout << std::fixed << std::setprecision(1) << test << std::endl;
// 输出结果会是86700.2

注意:float内部存储的还是近似值,但输出时会四舍五入到指定的小数位数。

3. 使用十进制浮点数类型(特殊场景)

如果你的场景对十进制精度要求极高(比如金融计算),可以使用专门的十进制浮点数库,比如Boost.Multiprecision的cpp_dec_float类型,不过这种方案比较重,一般业务场景不需要。

内容的提问来源于stack exchange,提问作者gear

火山引擎 最新活动