为什么许多(旧)程序使用floor(0.5 +输入)而不是round(输入)?

mar*_*zzz 80 c++ rounding floor

差异存在于返回值中,我相信这些输入可以打破平局,比如这段代码:

int main()
{
    std::cout.precision(100);

    double input = std::nextafter(0.05, 0.0) / 0.1;
    double x1 = floor(0.5 + input);
    double x2 = round(input);

    std::cout << x1 << std::endl;
    std::cout << x2 << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

哪个输出:

1
0
Run Code Online (Sandbox Code Playgroud)

但它们最终只是不同的结果,人们选择其首选的结果.我看到很多"旧的"C/C++程序floor(0.5 + input)而不是使用round(input).

有历史原因吗?最便宜的CPU?

hac*_*cks 113

std::round在C++ 11中引入.在此之前,只有std::floor程序员可以使用它.

  • @markzzz - C++标准库不会自动继承C的标准库.有仔细挑选和选择继续.他们花了12年才同步到C99. (11认同)
  • 重要的是要注意[正在使用的方法打破一些输入](/sf/answers/1704362621/)并且C++ 11依赖于C99而C++ 03依赖于C90哪种转到@markzzz点. (3认同)
  • @haccks:的确如此。IMHO C在数学函数方面一直领先于C ++,直到C ++ 11。 (2认同)

Bat*_*eba 18

没有任何历史原因.这种偏差自年初以来一直存在.当他们感到非常非常顽皮时,民谣会这样做.这是对浮点运算的严重滥用,许多经验丰富的专业程序员都会这样做.即使是Java标准版也达到了1.7版本.有趣的家伙.

我的猜想是,在C++ 11之前,一个体面的开箱即用的德国舍入功能尚未正式发布(尽管C在C99中获得了它们),但这并不是采用所谓替代方案的借口.

事情就是这样: floor(0.5 + input)并不总能恢复与相应std::round调用相同的结果!

原因是非常微妙的:德国四舍五入的截止点,a.5对于一个整数,a是宇宙的巧合属性,是一个二元理性.因为这可以在IEEE754浮点中精确表示,直到52的2次幂,然后舍入无论如何std::round都是无操作,总是正常工作.有关其他浮点方案,请参阅文档.

但是添加0.5到a double会导致不精确,导致某些值略微下降或过冲.如果你考虑一下,将两个double值加在一起 ​​- 这是不知情的否定转换的开始 - 并且应用一个非常强大的输入函数(例如舍入函数),必然会流下眼泪.

不要这样做.

参考:为什么Math.round(0.49999999999999994)返回1

  • 评论不适用于扩展讨论; 这个对话已经[转移到聊天](http://chat.stackoverflow.com/rooms/159106/discussion-on-answer-by-bathsheba-why-do-lots-of-old-programs-use-floor0- 5). (2认同)
  • [`nearbyint()`](http://en.cppreference.com/w/cpp/numeric/math/nearbyint) 通常比 [`round()`](http://en.cppreference. com/w/cpp/numeric/math/round),因为 `nearbyint` 使用当前的舍入模式而不是时髦的 tiebreak 远离 `round()` 的零(x86 甚至没有硬件支持,尽管 ARM做)。两者都在 C++11 中添加到 C++。 (2认同)

Mic*_*Roy 9

我认为这是你犯错误的地方:

但它们最终只是不同的结果,人们选择其首选的结果.我看到许多使用floor(0.5 +输入)而不是round(输入)的"旧"C/C++程序.

事实并非如此.您必须为域选择正确的舍入方案.在财务应用程序中,您将使用银行家的规则进行回合(顺便说一句,不使用浮动).但是,在采样时,使用static_cast<int>(floor(f + .5))较少的采样噪声进行舍入,这会增加动态范围.当对齐像素,即将位置转换为屏幕坐标时,使用任何其他舍入方法将产生孔,间隙和其他伪像.

  • 使用标准整数(缺乏)舍入,零和负一之间的所有值都会“消失”,或者更确切地说改变符号(相同的值和 fo 0 到 + 1 输入),所有负值至少偏移一位。这是添加了失真的一点噪音。 (2认同)

Miv*_*ott 5

一个简单的原因可能是有不同的四舍五入方法,因此除非您知道所使用的方法,否则可能会得到不同的结果。

使用floor(),可以使结果保持一致。如果浮点数为 0.5 或更大,则将其添加到下一个整数。但 0.49999 只会去掉小数。