<functional>:加上整数上的<long>()会产生意外结果</long> </functional>

时间:2014-02-25 16:20:48

标签: c++ g++

我不明白为什么在这两种情况下我没有得到相同的结果:

#include <iostream>
#include <vector>
#include <numeric> // for accumulate
#include <functional> // for plus()
using namespace std;

int main() {
    long long i = (long long)  0xFFFFFFFF + 2;
    cout << i << endl;

    vector<int> v;
    v.push_back(0xFFFFFFFF);
    v.push_back(2);

    long long r = accumulate(v.begin(), v.end(), 0, plus<long long>());
    cout << r << endl;

    return 0;
}

任何想法?

编辑:正如下面正确指出的,这是由于int中的符号位我没有指望。 0x7FFFFFFF显然会更好地进行测试。另外,我错误地期望plus()的返回类型与accumulate()的返回类型相同,但情况并非如此:它基于third参数。

3 个答案:

答案 0 :(得分:6)

这里有两个问题:

  1. 数字0xFFFFFFFF不适合int(假设32位int s),因此在大多数实现中,存储在向量中的值实际上为-1。使用vector<unsigned int>vector<long long>可以解决此问题。

  2. accumulate返回的类型是从第三个参数推导出的类型。自您通过0后,这将是int。您应该传递0LL,以便它返回long long

  3. 这个包含两个修复程序的程序将返回正确的结果:

    #include <iostream>
    #include <vector>
    #include <numeric> // for accumulate
    #include <functional> // for plus()
    using namespace std;
    
    int main() {
        long long i = (long long)  0xFFFFFFFF + 2;
        cout << i << endl;
    
        vector<long long> v; //or vector<unsigned int>
        v.push_back(0xFFFFFFFF);
        v.push_back(2);
    
        long long r = accumulate(v.begin(), v.end(), 0LL, plus<long long>());
        cout << r << endl;
    
        return 0;
    }
    

答案 1 :(得分:1)

因为向量包含类型int而0xFFFFFFFF不适合它。尝试将其更改为long long

#include <iostream>
#include <vector>
#include <numeric> // for accumulate
#include <functional> // for plus()
using namespace std;

int main() {
    long long i = (long long)  0xFFFFFFFF + 2;
    cout << i << endl;

    vector<long long> v;
    v.push_back(0xFFFFFFFF);
    v.push_back(2);

    long long r = accumulate(v.begin(), v.end(), 0LL, plus<long long>());
    cout << r << endl;

    return 0;
}

修改

此外,正如interjay所指出的,第三个参数应该具有类型long long,因为accumulate使用它来推导出结果类型。

答案 2 :(得分:1)

您的vector商店类型int可能是32位类型。从4.7 / 3我们学到:

  

如果目标类型已签名,则值可以保持不变   以目标类型(和位字段宽度)表示;除此以外,   该值是实现定义的。

换句话说,您的值0xFFFFFFFF无法在目标签名类型中表示,因此结果是实现定义的。在这种情况下,它很可能采用了明显的二进制结果并在向量中存储了-1。然后当您执行accumulate时,它会添加-1(因为它不会更改存储的-1)和2,从而导致1被打印。

您很可能希望将long long存储在向量中(因为您总结的值大于32位可以容纳),并且如其他答案中所述,您还需要传递0LL累积以强制它推断出正确的返回类型。