我被困在我的项目中。我实际上找到了多个值的平均值。我有10个平均值。总和正在给出正确的结果,即我添加负数并且结果也是负数,但是当要找到平均值的值具有高幅度时,存储汇总的16位寄存器给出正面价值。这里出了什么问题。
void SmoothArray()
{
val = 0;
for(k=0;k<10;k++)
{
cc = array[k];
val += cc;
}
val /= 10;
}
当此数组中有许多位置为负数时,求和是错误的,这是正数。使用C语言。数组是无符号短,而val是短
答案 0 :(得分:1)
如果我总是将负值加到16位寄存器会发生什么
您将有未定义的行为。我们假设您的int
是16位,并且您要添加两个int
值INT_MIN
和-1
,它将调用未定义的行为。在大多数系统中,您最终会获得正值。
使用较宽类型的变量对您的值求和,例如声明类型为val
的{{1}},保证至少为32位宽。
答案 1 :(得分:0)
Sum很可能使用2的补码代码存储(参见https://en.wikipedia.org/wiki/Two%27s_complement)。当您达到最低负值并尝试将其递减1时,您将获得最大可能的正值。
看起来你需要使用32位变量来存储求和值。
答案 2 :(得分:0)
正如其他人所说,问题的原因是溢出。
这是另一种获取大量值的平均值且溢出风险较小的方法,如果您可以对平均值进行提示。它基于以下公式:
avg(x) = avg(x - hint) + hint
例如,如果您知道您的值都在-200到-300之间,则可以使用hint = -250
。现在,您可以在-50和+50之间添加值,而不是在-200和-300之间添加值。溢出的风险要弱得多,精度也不会有任何损失。
实际上,这通常用于在计算大量浮点值的平均值时提高精度
答案 3 :(得分:0)
OP目前的代码已经溢出。
当然,使用更宽的整数是@ouah
所回答的最简单的方法否则,为防止溢出,请考虑部分求和。我们假设变量是int, int[]
void SmoothArray(void) {
val_msds = 0;
val_lsd = 0;
for(k=0;k<10;k++) {
cc = array[k];
val_msds += cc/10;
val_lsd += cc%10;
}
val = val_msds + val_lsd/10;
}
只要数组元素的数量(在OP示例中为10)小于sqrt(INT_MAX)
,此方法就可以正常工作。