我有一个包含整数值的向量,我希望求和。然而,它总计错误 - 如果向量在-10到10之间保持10个整数,那么我的总数不应该是18446744073709551602
。
我声明了向量,并用值填充它:
std::vector<int> X;
for ( int i = 0; i < readings.size() ; ++i ) {
X.push_back(readings[i].x);
然后我总结并显示:
unsigned long temptotal = 0;
for ( int i = 0; i < readings.size() ; ++i ) {
std::cout << "Value in X: " << X[i] << std::endl;
temptotal += X[i];
}
std::cout << "Temp total: " << temptotal << std::endl;
产生以下输出:Temp total: 18446744073709551603
。
当我逐步完成GDB中的求和循环时(temptotal += X[i];
),我可以print X[i]
:
(gdb) p X[i]
$1 = (reference) @0x100100c80: -1
在添加之前和之后打印temptotal
:
(gdb) p temptotal
$2 = 0
(gdb) p temptotal
$3 = 18446744073709551615
我很确定我正在添加内存位置而不是内存位置中的值 - 我可能错了 - 但我不确定为什么我不在{{1}添加值}}。当我使用X[i]
中的值填充X
时,它们是readings[i].x
s,然后我将其输入到double
s。这是我的错误吗?检查GDB时,int
值的类型转换应该是int,或者至少是某种类型的数据:
readings[i].x
我很难过;如果有人能说明为什么我没有添加我认为我正在添加的内容,我将不胜感激。
EDIT
这是从(gdb) p (int)readings[i].x
$1 = -1
到int
的投射。我把它翻过来,按下“提交问题”并发现我的错误。虽然,我仍然不明白为什么它正在做它正在做的事情 - 任何关于它的光线都会很精彩 - 为什么,如果我在unsigned long
添加int
,它不接受unsigned long
的值吗?
答案 0 :(得分:4)
这是因为您的temptotal
未签名。添加到其中的所有数字都是解释为无符号,因此小负数会成为two's complement representation中的大正数。
答案 1 :(得分:2)
不,你距离你的unsigned long
只有1分,它正在包裹着。
另外,请使用std::accumulate
:
result = std::accumulate(readings.begin(), readings.end(), 0);
答案 2 :(得分:2)
您在编辑中询问了为什么会发生这种情况。这是由于内存中积分类型的二进制表示。
在unsigned int
的简单情况下,您可以将任何正数字视为二进制数的直接表示,即
1 == 0b1
2 == 0b10
...
42 == 0b101010
每个数字都存储在一些有限的内存中,而int
通常是32位(或4个字节)。这意味着上面表示左侧的所有位都是零。
然而,int已签名,因此必须将信息存储在某处。碰巧是Twos complement是二进制中有符号整数的方便二进制表示(读取它)。对int
s
0 = 0b0
-1 = 0b11111111111111111111111111111111 (32 bits of all ones)
正如您现在可能已经意识到的那样,当您将int
转换为unsigned int
而不是负数时,由于这些数字的二进制表示,您会得到一个非常大的正数。通常,您不希望在计算中混合使用无符号整数和有符号整数,除非您确切知道自己在做什么。