Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arduino算术错误负结果_Arduino - Fatal编程技术网

Arduino算术错误负结果

Arduino算术错误负结果,arduino,Arduino,我正在尝试将52乘以1000,但结果是否定的 int getNewSum = 52 * 1000; 但是下面的代码给出了一个否定的结果:-13536在维基百科和其他地方对表示如何工作的解释可能比这里更好。我在这里要做的是带你了解你的确切例子的工作原理 Arduino上的int类型使用16位表示,以2的补码表示(请记住,其他Arduino使用32位,但您的使用16位)。这意味着正数和负数都可以存储在这16位中,如果设置了最左边的位,则该数字被视为负数 发生的情况是,您溢出了可用于存储正数的位数

我正在尝试将52乘以1000,但结果是否定的

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
类型替换为更大的数据类型。如前所述,我们可以使用不同的整数类型:

  • int:
    • 16位:从-32768到32767
    • 32位:从-2147483648到2147483647
  • 无符号整数:从0到65535
  • 长:从2147483648到2147483647
  • 无符号长:从0到4294967295
  • 解决方案2:


    只有在算术中有一些分母足够大的除法时,这才有效。在Arduino编译器中,乘法在除法之前计算。所以,如果你的方程中有一些除法,试着用括号把它们封装起来。例如,如果您有
    a*b/c
    将其替换为
    a*(b/c)

    您可能需要阅读,特别是它的限制,以及它对表示的使用。一旦你了解了二进制整数实际上是如何存储的,你就会对发生的事情有更多的了解。例如35209/3返回负数。INTA、b、c;c=a/b
    0011 0100 1101 1111