通过在 GNU C++17 中以不同的方式(几乎相似)进行相同的计算,我得到了不同的答案

I am getting different answer by doing the same calculation in different ways ( which are almost similar ) in GNU C++17

我基本上是想找到 2 乘以 5e+8 除以 3 得到的商得到的数。我尝试了几种方法,如 GNU C++17 代码片段所示,并得到了正确的结果仅在方法 2 和 4 中回答。我最初期望它是某种溢出情况,但是 signed int 可以存储的最大数量比 2e+9 多一点,这比我处理的数字大得多所以我认为问题可能出在其他地方。如果有人可以提供帮助,那就太好了。提前致谢:)

using namespace std;

int main(){

// I basically wan't to calculate: 2 * 500000000/3 ( 2 * 5e+8 / 3)

    // Approach 1
    cout<<2 * 500000000 / 3<<"\n";  // output : 333333333 (nine 3s) WRONG!

    // Approach 2
    int a = 500000000/3;    // output : 333333332 (eight 3s) CORRECT!
    cout<<2 * a<<"\n";

    // Approach 3
    a = 2 * 500000000/3;    // output : 333333333 (nine 3s) WRONG!
    cout<<a<<"\n";

    // Approach 4 
    cout<<500000000 / 3 * 2<<"\n";  // output : 333333332 (eight 3s) CORRECT!
}

我们可以验证这两个答案实际上都是正确的。

(2*500,000,000)/3 = (1000,000,000)/3=333,333,333

(500,000,000/3)*2 = (166,666,666)*2 =333,333,332

这与 C++ 整数除法总是向下取整有关,与溢出无关。可以说 333,333,333 是 "real" 答案 333,333,333.333...

更准确的近似值

操作顺序很重要。当你计算 2 * 500000000 / 3 时,它等于

floor(floor(2 * 500000000)/3)

(在实数运算的数学意义上),而第二种方法 2 * (500000000/3) 的计算等于

floor(2 * floor(500000000/3)).

这是因为每个整数算术运算都是总是然后向零舍入(对于非负结果与floor相同)。

方法三相当于方法一,方法四相当于方法二