gpt4 book ai didi

c++ - C++舍入算法中的0.501,C++中的Excel ROUND

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:43:51 26 4
gpt4 key购买 nike

我有以下用于常规舍入的遗留代码(四舍五入,像 Excel ROUND 函数中那样四舍五入)。我对这段代码有疑问。

  1. 为什么使用 0.50 倍加法?我明白,应该使用 0.5 加法来实现“四舍五入”条件,但为什么会有 0.501?我们的经验表明 0.501 在实践中效果很好,它引入的舍入误差(RoundFloat 与 Excel ROUND 不同的情况)比 0.5 少得多。这是为什么?浮点计算是否会偏向于给出比理想情况下更小的值,而 0.501 可以纠正这些偏差?
  2. 虽然 0.501 在大多数情况下效果很好,但某些值存在问题,例如RoundFloat(7.33499999999, 2) 给出 7.34,但这是错误的,正确答案应该是 7.33。如何改进算法以获得正确的结果?可以尝试使用 0.50000001 而不是 0.501,但总是有一些参数会用这种算法给出错误的结果。 什么是正确的算法,是否有用于 Excel 样式 ROUND 舍入的内置 C++ 函数。

提前致谢!

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;
}

最佳答案

(我将此答案限制为 IEEE754 float ,这是 Excel 使用的。)

0.5(四舍五入 pivot)被 Excel 使用,因为这是正确的做法。请注意,0.5(作为二进有理数)可以精确地用 float 表示。

使用 0.501 是任意的、过度不对称的,并且表明缺乏对浮点的理解。

可以得到一些虚假效果,因为一个数字略小于 0.5,0.5 作为最接近的可表示数字。因此,即使确实应该向下舍入,您的“少一点”数字也会向上舍入。但这更多是因为数字一开始就无法准确表示。因此,尽管 0.5 会给您带来一些奇怪的效果,但它平均会比 0.501 或类似值更准确。做一些像增加超过 0.5 的事情会弄乱四舍五入是最佳的情况。

虽然我专注于 0.5,但所有舍入效果都可以用相同的方式解释,尽管在其他情况下舍入轴本身可能无法表示。

学习接受效果,就像 Excel 一样。 (请记住,Excel 可以通过对用户隐藏这些影响的方式来格式化数据,因此它似乎在做一些比实际更特别的事情。)如果计算精确到超过 15 个有效位是绝对关键的数字,然后使用支持任意精度的类。

关于c++ - C++舍入算法中的0.501,C++中的Excel ROUND,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35556434/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com