<Functional>:<long>整数上的加号()给出意外的结果

<Functional>: plus<long>() on integers gives unexpected result

本文关键字:gt lt 意外 结果 Functional long 整数      更新时间:2023-10-16

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

#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() 的返回类型相同,但事实并非如此:它基于第三个参数。

这里有两个问题:

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

  2. accumulate返回的类型是从第三个参数推导的类型。既然你通过了0,这就int了。您应该传入0LL,以便它返回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; //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;
}
<</div> div class="answers">

因为您的向量包含类型 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,因为累积使用它来推断结果类型。

您的vector存储类型int,这可能是 32 位类型。从 4.7/3 开始,我们了解到:

如果

目标类型是有符号的,则值保持不变(如果可以 以目标类型(和位域宽度)表示;否则 该值是实现定义的。

换句话说,你的值0xFFFFFFFF不能在目标签名类型中表示,因此结果是实现定义的。在这种情况下,它很可能采用明显的 twos-comp 结果并在向量中存储-1。然后当你做accumulate时,它会添加-1(因为它不会改变存储的-1)和2,导致1被打印出来。

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