C ++复合赋值和类型转换问题

时间:2019-02-23 03:01:34

标签: c++

我正在C ++中计算组合(15,7)。

  1. 我首先使用以下代码,并由于type promotion error而得到错误的答案。

    #include <iostream>
    
    int main()
    {
        int a = 15;
        double ans = 1;
        for(int i = 1; i <= 7; i++)
            ans *= (a + 1 - i) / i;
        std::cout << (int) ans;
    
        return 0;
    }
    

    输出: 2520

  2. 因此我将ans *= (a + 1 - i) / i;更改为ans *= (double)(a + 1 - i) / i;,但仍然得到错误的答案。

    #include <iostream>
    
    int main()
    {
        int a = 15;
        double ans = 1;
        for(int i = 1; i <= 7; i++)
            ans *= (double) (a + 1 - i) / i;
        std::cout << (int) ans;
    
        return 0;
    }
    

    输出: 6434

  3. 最后,我尝试了ans = ans * (a + 1 - i) / i,它给出了正确的答案。

    #include <iostream>
    
    int main()
    {
        int a = 15;
        double ans = 1;
        for(int i = 1; i <= 7; i++)
            ans = ans * (a + 1 - i) / i;
        std::cout << (int) ans;
    
        return 0;
    }
    

    输出: 6435

有人可以告诉我为什么第二个不起作用吗?

2 个答案:

答案 0 :(得分:4)

如果打印出public void aButton() { start = mediaPlayer.getCurrentPosition(); } public void bButton() { pressedCount += 1; System.out.println("AB Button Count: " + pressedCount); stop = mediaPlayer.getCurrentPosition(); mediaPlayer.seekTo(start); if(mediaPlayer.getCurrentPosition() == stop){ mediaPlayer.seekTo(start); } } 而不将其投射到ans上,将会看到第二个结果是(int)。这很接近6434.9999999999990905052982270717620849609375的正确答案,因此显然不再是类型提升错误。

不,这是经典的floating point inaccuracy。当您写6535时,您所做的等同于:

ans *= (double) (a + 1 - i) / i

将此与第三个版本进行比较:

ans = ans * ((double) (a + 1 - i) / i);

前者先进行除法,然后相乘。后者从左到右操作,因此乘法先于除法。操作顺序的这种变化导致两者的结果略有不同。浮点计算对操作顺序极为敏感。

快速解决方案:不要截断结果; round

更好的解决方法:请勿将浮点数用于积分算术。保存除法,直到完成所有乘法。使用ans = ans * (a + 1 - i) / i; long甚至是big number library

答案 1 :(得分:0)

第一个不起作用,因为那里有整数除法。

第二个和第三个之间的区别是:

ans = ans * (double(a + 1 - i) / i); // second is equal to this

vs:

ans = (ans * (a + 1 - i)) / i; // third is equal to this

所以差异是按乘法和除法的顺序进行的。如果您将双精度取整为整数而不是简单地舍弃小数部分,将会得到相同的结果。

std::cout << int( ans + 0.5 ) << std::endl;