C++小数精度、四舍五入的疑惑
double preClosePrice = 0.8350; double rate = 0.1; double low = preClosePrice * (1 - rate);// low= 0.7514999999 double ret1 = low * 1000;//751.5 double ret2 = low / 0.001;//751.49999 double ret3 = std::round(ret1);//752 double ret4= std::round(ret2);//751
也就是说 low * 1000 不等于 low / 0.001,这就导致之后的四舍五入结果也不一样了。原因估计就是0.001 并不是精确的,导致结果扩大一千倍之后,小数位数一个是4一个是5。
正确的结果是751.5,而low / 0.001得到的结果是751.49999。事实上,由于low是0.75149999,既是乘1000也有可能结果是751.49999(而不是751.5)。因此,合理的解决方法可能不在于是乘还是除,而是其他的方案。。
方案1:先乘后除:(比先除后乘要好):
double roundToPrecision(double value, double priceTick)
{int decimalPlaces = 0;while (priceTick < 1 && decimalPlaces < 5){priceTick *= 10;decimalPlaces++;}double factor = std::pow(10.0, decimalPlaces);return std::round(value * factor) / factor;
}
方案2 :+0.5
// 四舍五入函数
double roundToPrecision(double value, double priceTick)
{int decimalPlaces = 0;while (priceTick < 1 && decimalPlaces < 5){priceTick *= 10;decimalPlaces++;}const double factor = std::pow(10.0, decimalPlaces);const qint64 ret = (qint64) (value * factor + 0.5);return ret / factor;
}
部分测试:
// double preClosePrice = 0.8350;
// double rate = 0.1;
// double tickSize = 0.001;
//
// double high = preClosePrice * (1 + rate);
// double low = preClosePrice * (1 - rate);
// // 计算缩放因子
// double factor = 1.0 / tickSize;
//
// // 使用整数运算避免浮点误差
// qint64 scaledPrice = qRound64(low * factor);
// const double low2 = (scaledPrice) * tickSize;
//
// double ret = 0.75149999*10000;
// qint64 scaledPrice2 = qRound64(ret);
// double ret2 = scaledPrice2*tickSize;
// const double low3 = (scaledPrice2) * tickSize;
// qDebug() << low2;
// qDebug() << low3;// double preClosePrice = 0.8350;
// double rate = 0.1;
// double high = preClosePrice * (1 + rate);
// double low = preClosePrice * (1 - rate);
// double ret1 = low * 1000;
// double ret2 = low / 0.001;
// double ret3 = qRound64(ret1);
// double ret4= std::round(ret2);
// const double low2 = qRound64(low * 1000) / 1000.0;
// const double low3 = std::round(low / 0.001) * 0.001;// qDebug() << low2;
// qDebug() << low3;
// return 0;