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

这些差异存在于返回的值中,我认为这些返回值给出了关于打破平局的输入,例如 这个密码:

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

产出:

1
0

但它们最终只是不同的结果,一个人选择自己喜欢的结果。我看到很多“旧”的 C/C + + 程序使用 floor(0.5 + input)而不是 round(input)

有什么历史原因吗? CPU 最便宜?

17822 次浏览

根本没有什么历史原因。这种离经叛道的行为从2010年就开始了。这是对浮点数算法的滥用,许多经验丰富的专业程序员都会上当。甚至 Java 的 bods 也达到了1.7版本。有趣的家伙。

我的猜测是,一个像样的开箱即用的舍入函数直到 C + + 11(尽管 C 在 C99中得到了他们的)才正式可用,但这并不是采用所谓的替代方案的借口。

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

原因很微妙: 四舍五入的截止点,整数 aa.5二元理性。由于这可以精确地用 IEEE754浮点数表示,直到2的52次方,此后四舍五入是不可操作的,因此 std::round总是能正常工作。对于其他浮点方案,请参考文档。

但是,将 0.5添加到 double可能会引入不精确性,从而导致某些值略低于或超调。如果你仔细想想,把两个 double值加在一起——这是不知情的二进制转换的开始——然后应用一个输入函数的非常强的函数(比如舍入函数) ,注定会以悲剧收场。

不要这样做。

参考资料: 为什么 Math.round (0.4999999999999999999994)返回1?

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

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

使用 floor () ,您可以与结果保持一致。如果浮点数是0.5或更大,那么加上浮点数就会增加到下一个整型数。但是。49999只会去掉小数。

许多程序员采用他们在使用其他语言编程时学到的习惯用法。并非所有语言都有 round()函数,在这些语言中,通常使用 floor(x + 0.5)作为替代函数。当这些程序员开始使用 C + + 时,他们并不总是意识到有一个内置的 round(),他们继续使用他们习惯的样式。

换句话说,仅仅因为您看到了许多执行某些操作的代码,并不意味着有充分的理由这样做。您可以在每种编程语言中找到这方面的例子。记住 斯特金法则:

百分之九十的东西都是垃圾

我想这就是你犯错的地方:

但它们最终只是不同的结果,一个人选择它 我看到很多“老”的 C/C + + 程序使用 floor (0.5 + 输入)而不是整数(输入)。

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