2013-12-15 40 views
0

我1000试图倍52,我得到一个否定的结果Arduino的算术错误阴性结果

int getNewSum = 52 * 1000; 

但下面的代码ouputting阴性结果:-13536

+1

您可能需要阅读[关于Arduino int类型的文档](http://arduino.cc/en/Reference/int),特别是它的限制,以及它对[two's complement]的使用(https:// en .wikipedia.org/wiki/ Two's_complement)表示。一旦你了解了二进制整数是如何存储的,你就会对所发生的事情有更多的了解。 –

回答

1

怎样的解释two's complement代表作品可能在维基百科和其他地方比这里更好。我要在这里做的是带你通过你的确切例子的运作。

Arduino中的int类型用16位表示,用二进制补码表示(请记住,其他Arduinos使用32位而不是16位)。这意味着正数和负数都可以存储在这16位中,如果最左边的位被设置,则该数字被认为是负数。

发生了什么事情是,你正在溢出你可以用来存储一个正数的位数,并且(意外的是,就你所关心的)来设置符号位,从而表明这个数字是负数。

0000 0000 0011 0100 

(2^5 + 2^4 + 2^2 = 52)

但是,结果:

在关于您的Arduino 16位,十进制52将二进制作为表示52000 - - 52乘以由1000的最终会溢出int的量值位,把一个在上端的符号位“1”:

*----This is the sign bit. It's now 1, so the number is considered negative. 
1100 1011 0010 0000 

(典型地,计算机整数运算和相关联的编程语言d不会保护你免于这样做,原因很多,主要与效率有关,现在主要与历史有关)。

因为左侧的符号位已设置,所以要将该数字转换回来成从假定二进制补码表示小数,我们假定它是一个负数,然后先取一的补(翻转所有位):

0011 0100 1101 1111 

- 它代表13535 - 添加一个吧,产生13,536,并称之为负值:-13,536,你看到的价值。

如果你在一般情况下阅读了两个补码/整数表达式,你会得到它的挂钩。

与此同时,这可能意味着您应该寻找更大的类型来存储您的号码。 Arduino有无符号整数,和一个long类型,它将使用四个字节来存储你的数字,给你的范围从-2,147,483,648到2,147,483,647。如果这对你来说已经足够了,那么你应该改用long而不是int

0

马特的答案已经是在发生的事情的深入的解释非常好,但是对于那些寻找一个更实际的答案:

问题:

这种情况经常用于Arduino的程序员,当他们尝试在正常整数(int)中赋值(=等号)乘法结果。如前所述,当结果大于编译器分配给变量的内存大小时,会发生溢出。

解决方案1:

最简单的办法是考虑你的需要更大的数据类型来代替int类型。正如this tutorialspoint.com tutorial解释有不同的整数类型,我们可以使用:

  1. INT:
    • 16位:从-32,768至32,767
    • 32位:从2,147,483,648到2,147,483,647
  2. unsigned int:从0到65,535
  3. 长:从2,147,483,648到2,147,483,647
  4. 无符号长:从0到4,294,967,295

解决方案2:

这只有你有足够大的分母一些分歧,在你的算术。在Arduino编译器中,乘法是在除法之前计算的。所以如果你的公式中有一些分歧,试着用圆括号封装它们。例如,如果您有b/c,请将其替换为(b/c)。