【发布时间】:2016-02-22 14:40:32
【问题描述】:
我有以下用于通常舍入的旧代码(四舍五入,类似于 Excel ROUND 函数中的舍入)。我对此代码有疑问。
- 为什么要使用 0.50x 加法?我知道,应该使用 0.5 加法来实现“四舍五入”条件,但为什么会有 0.501?我们的经验表明,0.501 在实践中效果很好,它引入的舍入误差(RoundFloat 与 Excel ROUND 不同的情况)比 0.5 少得多。这是为什么?浮点计算是否偏向于给出比理想情况下更小的值,而 0.501 可以纠正这些偏差?
- 虽然 0.501 在大多数情况下效果很好,但某些值存在问题,例如RoundFloat(7.33499999999, 2) 给出 7.34,但这是错误的,正确答案应该是 7.33。如何改进算法以获得正确的结果?可以尝试使用 0.50000001 而不是 0.501,但总有一些参数会给出错误的结果。 什么是正确的算法,是否有内置的 C++ 函数用于 Excel 风格的 ROUND 舍入。
提前致谢!
double LongLong( double value ) {
long long l = ( long long ) value;
return l;
}
double RoundFloat( double * value, double * tonearest ) {
double ad;
long long mzr;
double resval;
if ( ( *tonearest < 0 ) || ( *tonearest > 6 ) ) return * value;
if ( *value < 0.000000001 )
ad = -0.501;
else
ad = 0.501;
mzr = LongLong(*value);
resval = *value - mzr;
switch ( ( long ) *tonearest )
{
case 0 : resval= LongLong( resval+ad);
case 1 : resval= LongLong( resval*10+ad)/10;
case 2 : resval= LongLong( resval*100+ad)/100;
case 3 : resval= LongLong( resval*1000+ad)/1000;
case 4 : resval= LongLong( resval*10000+ad)/10000;
case 5 : resval= LongLong( resval*100000+ad)/100000;
case 6 : resval= LongLong( resval*1000000+ad)/1000000;
default: resval= resval;
}
resval = resval+mzr;
return resval;
}
【问题讨论】:
标签: c++ algorithm floating-point rounding