C++中float赋值/存入vector时被舍入的原因及解决方法
关于nlohmann/json浮点数转float时舍入的问题解答
现象原因
nlohmann/json库的json对象默认将浮点数以double类型存储(双精度,约15-17位有效数字),而float是单精度类型,仅能保留约6-7位有效数字。当你把json中的浮点数赋值给float或存入vector<float>时,会触发double到float的隐式转换,超出float精度范围的部分会被舍入。
而直接打印json中的浮点数时,程序输出的是内部存储的double原始值,所以能显示完整的有效数字,不会出现舍入。
举个实际代码示例:
#include <nlohmann/json.hpp> #include <iostream> #include <vector> using json = nlohmann::json; int main() { json j = R"({"num": 0.1234567890123456789})"_json; std::cout << "直接打印json值: " << j["num"] << std::endl; float f = j["num"]; std::cout << "赋值给float后的值: " << f << std::endl; std::vector<float> vec; vec.push_back(j["num"]); std::cout << "vector<float>中的值: " << vec[0] << std::endl; return 0; }
运行输出:
直接打印json值: 0.12345678901234568
赋值给float后的值: 0.123457
vector中的值: 0.123457
可以看到,float只保留了前7位有效数字,后面的部分被舍入了。
解决方法
使用double类型替代float
这是最直接的解决方案,把接收变量改成double,容器改成vector<double>,这样就能完整保留json存储的浮点数精度,不会出现舍入:double d = j["num"]; std::vector<double> vec_d; vec_d.push_back(j["num"]); // 打印结果会和直接输出json值一致 std::cout << "赋值给double后的值: " << d << std::endl;若必须使用float
要明确float的精度限制是硬件和标准决定的,无法突破。如果你的浮点数有效数字不超过7位,转换后不会有舍入;如果超出范围,舍入是必然的,只能接受这个精度损失。没有办法让float存储超过其精度范围的数值。
内容的提问来源于stack exchange,提问作者SADL
相关产品推荐
相关产品推荐

