Arduino算术错误负结果
我正在尝试将52乘以1000,但结果是否定的Arduino算术错误负结果,arduino,Arduino,我正在尝试将52乘以1000,但结果是否定的 int getNewSum = 52 * 1000; 但是下面的代码给出了一个否定的结果:-13536在维基百科和其他地方对表示如何工作的解释可能比这里更好。我在这里要做的是带你了解你的确切例子的工作原理 Arduino上的int类型使用16位表示,以2的补码表示(请记住,其他Arduino使用32位,但您的使用16位)。这意味着正数和负数都可以存储在这16位中,如果设置了最左边的位,则该数字被视为负数 发生的情况是,您溢出了可用于存储正数的位数
int getNewSum = 52 * 1000;
但是下面的代码给出了一个否定的结果:-13536在维基百科和其他地方对表示如何工作的解释可能比这里更好。我在这里要做的是带你了解你的确切例子的工作原理
Arduino上的int类型使用16位表示,以2的补码表示(请记住,其他Arduino使用32位,但您的使用16位)。这意味着正数和负数都可以存储在这16位中,如果设置了最左边的位,则该数字被视为负数
发生的情况是,您溢出了可用于存储正数的位数,并且(就您而言,是意外地)设置了符号位,从而指示该数字为负数
在Arduino上的16位中,十进制52将用二进制表示为:
0000 0000 0011 0100
(2^5+2^4+2^2=52)
但是,将52乘以1000(52000)的结果将溢出整数的大小位,在末尾的符号位中放入“1”:
*----This is the sign bit. It's now 1, so the number is considered negative.
1100 1011 0010 0000
(通常情况下,计算机整数算术和相关编程语言不会保护您不做类似的事情,原因有很多,主要与效率有关,而且大部分是历史原因。)
由于设置了左端的符号位,为了将该数字从其假定的2的补码表示形式转换回十进制,我们假定它是负数,然后首先取1的补码(翻转所有位):
--它代表13535-,再加上一个,得到13536,称之为负:-13536,你看到的值
如果你通读了2的补码/整数表示法,你就会明白其中的诀窍
同时,这可能意味着你应该寻找一个更大的类型来存储你的号码。Arduino有一个无符号整数和一个类型,它将使用四个字节来存储您的数字,给您一个从-2147483648到2147483647的范围。如果这对你来说已经足够了,你也许应该改用
long
而不是int
马特的答案已经是一个非常好的深入解释,但对于那些寻找更多TL的人来说;dr实用答案:
问题:
当Arduino程序员试图将算术(通常是乘法)的结果赋值(=等号)到一个普通整数(int
)时,这种情况经常发生。如前所述,当结果大于编译器分配给变量的内存大小时,就会发生溢出
解决方案1:
考虑到您的需要,最简单的解决方案是将int
类型替换为更大的数据类型。如前所述,我们可以使用不同的整数类型:
- 16位:从-32768到32767
- 32位:从-2147483648到2147483647
只有在算术中有一些分母足够大的除法时,这才有效。在Arduino编译器中,乘法在除法之前计算。所以,如果你的方程中有一些除法,试着用括号把它们封装起来。例如,如果您有
a*b/c
将其替换为a*(b/c)
您可能需要阅读,特别是它的限制,以及它对表示的使用。一旦你了解了二进制整数实际上是如何存储的,你就会对发生的事情有更多的了解。例如35209/3返回负数。INTA、b、c;c=a/b
0011 0100 1101 1111