Qt环境下double与quint64转换数值异常问题咨询
解答:MinGW环境下Qt中整数与浮点数除法的精度疑惑
先回顾一下你的代码和运行结果:
quint64 a = 11; double b = 0.1; double v = a / b; quint64 v1 = a / b; quint64 v2 = v; quint64 v3 = (double)((double)a / (double)b); qDebug() << QObject::tr("v = %1, v1 = %2, v2 = %3, v3 = %4").arg(v).arg(v1).arg(v2).arg(v3);
运行输出:
"v = 110, v1 = 109, v2 = 110, v3 = 109"
为什么v1和v3的结果是109?
这一切的根源都是浮点数的精度限制:十进制的0.1无法被double类型精确表示——它在二进制中是一个无限循环的小数,double只能存储它的近似值,这个值其实是略大于十进制0.1的(具体是0.10000000000000000555...)。
当计算11 / 0.1时,实际是11除以这个略大的近似值,得到的结果是略小于110的浮点数(比如109.99999999999999)。
- 对于
v1 = a / b:这个略小于110的浮点数被直接强制转换为quint64,而C++中浮点数转整数是向零截断——直接丢掉小数部分,所以109.999...就变成了109。 - 对于
v3:你做了多层转换,但本质还是一样的——(double)a/(double)b得到的还是那个略小于110的浮点数,再转一次double也不会改变它的实际值,最终转quint64时依然被截断成109。
至于v2得到110,是因为当这个接近110的浮点数被存储到double变量v时,由于double的53位精度限制,这个值会被舍入到最接近的可精确表示的double值——也就是110。qDebug()输出v显示为110,也是因为它会对浮点数做格式化处理,把接近整数的数值显示为整数。
编译器是如何处理a / b语句的?
在C++的类型转换规则下,a / b的执行流程是这样的:
- 数值提升:因为
double的转换优先级高于quint64,所以编译器会先把quint64类型的a转换为double类型。 - 浮点数除法:执行
(double)a / b的浮点数运算,得到一个double结果。 - 结果转换:如果是直接赋值给
quint64(比如v1),就直接截断小数部分得到整数;如果是赋值给double变量(比如v),则会根据double的精度规则舍入存储。
如何让v3通过单行代码得到110的正确结果?
你需要对浮点数结果进行四舍五入,而不是直接截断。有两种常用方法:
方法1:使用标准库的四舍五入函数
需要包含<cmath>头文件:
quint64 v3 = static_cast<quint64>(std::round(static_cast<double>(a) / b));
方法2:使用Qt自带的四舍五入函数
Qt提供了qRound(),更适合Qt项目(无需额外包含头文件):
quint64 v3 = static_cast<quint64>(qRound(static_cast<double>(a) / b));
如果你的场景中b是固定的0.1,还可以完全避开浮点数运算,用整数乘法直接得到精确结果:
quint64 v3 = a * 10;
这种方法没有任何精度问题,是最优解,但只适用于除数是整数倒数的情况。
内容的提问来源于stack exchange,提问作者f0g
相关产品推荐
相关产品推荐

