简体   繁体   English

如果我不断将16位寄存器的负值求和会怎样?

[英]What happens if I sum negative values to a 16bit register constantly

I am stuck in my project. 我被困在我的项目中。 I am actually finding the average of multiple values. 我实际上正在找到多个值的平均值。 I have ten values to average. 我有十个平均值。 The sum is giving the correct result for some time that is I am adding the negative numbers and the result is also negative numbers, but when the values whose average is to be found has high magnitudes then the 16bit register in which the summmation is stored gives positive value. 在一段时间内,总和给出正确的结果,即我正在添加负数,结果也是负数,但是当要求平均值的值具有高幅度时,则存储求和的16位寄存器将给出正值。 What is going wrong in here. 这里出了什么问题。

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

In this when array has many locations negative the summation is wrong that is positive. 在这种情况下,当数组有很多位置为负时,总和是错误的。 C language used. 使用的C语言。 Array is unsigned short, while val is short 数组是unsigned short,而val是short

What happens if I sum negative values to a 16bit register constantly 如果我不断将16位寄存器的负值求和会怎样?

You will have undefined behavior. 您将有未定义的行为。 Let's say that for example your int is 16-bit and you are adding the two int value INT_MIN and -1 , it will invoke undefined behavior. 假设您的int是16位的,而您要添加两个intINT_MIN-1 ,它将调用未定义的行为。 In most systems you will end up with a positive value. 在大多数系统中,您将获得正值。

Use a variable of a wider type to sum your values, for example declare val of type long which guaranteed to be at least 32-bit wide. 使用更广泛类型的变量来求和您的值,例如声明long类型的val ,保证至少32位宽。

Sum is most probably stored using 2's complement code (see https://en.wikipedia.org/wiki/Two%27s_complement ). 总和很可能使用2的补码存储(请参阅https://en.wikipedia.org/wiki/Two%27s_complement )。 When you hit the lowest negative value and try to decrement it by one, you will get the largest possible positive value. 当您达到最低的负值并尝试将其减小1时,您将获得最大的正值。

Looks that you need to use 32-bit variable to store summed values. 看起来您需要使用32位变量来存储求和值。

As already said by others, the cause of your problem is an overflow. 正如其他人已经说过的,导致问题的原因是溢出。

Here is another way for taking average of a great number of values with less risk of overflow, provided you can have a hint on the average value . 这是获取大量平均值的另一种方法,可以减少溢出的风险, 前提是您可以对平均值进行提示 It is based on following formula : 它基于以下公式:

avg(x) = avg(x - hint) + hint

For example, if you know that your values are all between -200 and -300, you could take hint = -250 . 例如,如果您知道所有值都在-200到-300之间,则可以使用hint = -250 Now, instead of adding values between -200 and -300, you add values between -50 and +50. 现在,您不必添加-200至-300之间的值,而是添加-50至+50之间的值。 The risk of overflow is much weaker, without any loss in precision. 溢出的风险要弱得多,而不会损失任何精度。

In fact this is commonly used for increasing precision when calculating the average of a great number of floating point values 实际上,当计算大量浮点值的平均值时,通常用于提高精度

OP's present code is overflowing. OP的当前代码溢出。

Certainly using a wider integer is the simplest approach as answered by @ouah 当然,使用更宽的整数是@ouah回答的最简单方法

Otherwise, to prevent overflow, consider summing in parts. 否则,为防止溢出,请考虑分部分进行求和。 Let us assume variables are type int, int[] 让我们假设变量是int, int[]类型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; 
}

This approach work well as long as the number of array elements (10 in OP's example) is less than sqrt(INT_MAX) . 只要数组元素的数量(在OP的示例中为10)小于sqrt(INT_MAX)此方法就可以很好地工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM