如果我不断地将负值加到16位寄存器会发生什么

时间:2015-06-10 17:51:52

标签: c 16-bit

我被困在我的项目中。我实际上找到了多个值的平均值。我有10个平均值。总和正在给出正确的结果,即我添加负数并且结果也是负数,但是当要找到平均值的值具有高幅度时,存储汇总的16位寄存器给出正面价值。这里出了什么问题。

void SmoothArray()
{ 
    val = 0;
    for(k=0;k<10;k++)
    {
        cc = array[k];
        val += cc; 
    }
    val /= 10; 
}

当此数组中有许多位置为负数时,求和是错误的,这是正数。使用C语言。数组是无符号短,而val是短

4 个答案:

答案 0 :(得分:1)

  

如果我总是将负值加到16位寄存器会发生什么

您将有未定义的行为。我们假设您的int是16位,并且您要添加两个intINT_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),此方法就可以正常工作。