从看似相同的计算得到不同的输出

时间:2014-02-18 19:32:11

标签: c++ math

任何人都可以告诉我为什么第9行和第11行的计算看似相同,会产生两种不同的输出。我知道差异不是很大,但我使用这些值来绘制OpenGL的线条,差别很明显。

#include <iostream>
#include <cmath>

int main()
{
    int ypos=400;

    /// Output: 410.
    std::cout <<  400+(sin((90*3.14159)/180)*10) << std::endl;

    ypos=ypos+(sin((90*3.14159)/180)*10);
    /// Output: 409.
    std::cout << ypos << std::endl;

    return 0;
}

4 个答案:

答案 0 :(得分:6)

这是输出浮点数

 std::cout <<  400+(sin((90*3.14159)/180)*10) << std::endl;

但这是输出一个整数,所以会被截断

std::cout << ypos << std::endl;

答案 1 :(得分:5)

真实答案位于409.9999999附近。

这是输出double并四舍五入到410因为数学全部内联:

std::cout <<  400+(sin((90*3.14159)/180)*10) << std::endl;

因为ypos被声明为int,所以double值被截断409(这是从{{1}转换时定义的行为转到double):

int

请注意, 还可以通过为PI使用更好的常量来提高准确度:

ypos=ypos+(sin((90*3.14159)/180)*10);

/// Output: 409.
std::cout << ypos << std::endl;

但我仍会将结果存储在const double PI = 3.141592653589793238463; std::cout << 400+(sin((90*PI)/180)*10) << std::endl; 而不是double中,以避免截断。如果您需要整数结果,那么我将首先进行舍入:

int

答案 2 :(得分:3)

这是GCC's most common non bug

的一个实例

这就是浮动的行为方式。由于舍入错误,您无法得到确切的结果。它非常接近410,例如409.99999923。但是,如果将它打印为浮点数,默认情况下c ++舍入为6位数,从而为您提供410。在第二次,您将其分配给整数。在这种情况下,c ++不会执行舍入,而是执行截断。这就是为什么409。

答案 3 :(得分:1)

为了保持代码稳定以便你的OpenGL输出表现良好,你可能应该使用双精度完成所有(或尽可能多的)计算,这样截断效果就不会累积,最后(假设你需要一个整数像素数)或者总是舍入生成整数值或截断,但不能混合两者。