使用整数的C ++操作会产生负面结果

时间:2017-09-01 18:46:33

标签: c++ arduino

我正在调试Arduino中的“大”程序。在某些时候它开始抛出奇怪的结果,所以我跟着它进行了一个不应该给出负数的操作。 结果应该是248,625,因为它存储在一个int变量中(给我相同的-79)。我已经尝试过铸造int并应用ceil,floor,但没有成功。 任何帮助将不胜感激。

调试打印:

B -> (255*195)/200+0 = -79

代码:

// the setup routine runs once when you press reset:
void setup() {
  Serial.begin(115200);
}

// the loop routine runs over and over again forever:
void loop() {
  int _num_steps = 200;
  int _current_step = 195;
  int _delta_B = 255;
  int currentValues_B = 0;

  Serial.print(" B -> ");
  Serial.print("(");
  Serial.print(_delta_B);
  Serial.print("*");
  Serial.print(_current_step);
  Serial.print(")/");
  Serial.print(_num_steps);
  Serial.print("+");
  Serial.print(currentValues_B);
  Serial.print(" = ");
  Serial.println(((_delta_B*_current_step) / _num_steps) + currentValues_B);
  while(true){}
}

4 个答案:

答案 0 :(得分:2)

我的猜测是你的设备运行16位整数。如果我们用16位有符号整数和溢出进行数学运算:

True

您可以通过打印sizeof(int)

来验证整数的大小

答案 1 :(得分:2)

https://www.arduino.cc/en/Reference/Int

  

在Arduino Uno(以及其他基于ATMega的主板)上,一个int存储了一个   16位(2字节)值。这产生了-32,768到32,767的范围   (最小值-2 ^ 15,最大值(2 ^ 15) - 1)。

你可以尝试很长时间(在Arduino上是4字节)。我不一定会看到你打算做什么,但这也不会永远增长。如果它们可以永久增长,您需要处理包裹(或重置间隔或其他)的情况。此外,如果该值不应该变为负数,则可以使用无符号原始数据类型并将其正范围加倍。

答案 2 :(得分:1)

正如其他用户在评论中指出的那样,这是一个溢出问题。 鉴于" int"," long"等根据定义仅具有固定的最小位数(并且int最小数为16),则存在此问题。 可能你以前从未遇到过这个问题,因为现在有时候用32位实现int。

要确保每次都知道你的int类型使用的位数,你可以使用这样的东西:

typedef int32_t myint;
typedef u_int32_t myuint;

然后只使用myint。通过这种方式,您可以确切地知道所使用的位数,如果您决定根据一些新需求更改实现,则可以在一个位置更改它。

答案 3 :(得分:1)

由于int使用16位n Arduino表示,因此您必须依靠基本数学来获得所需的答案。

您正在尝试计算(A*B)/C

(A*B)/C = ((k1*C+a) * (k2*C+b)/C,其中
k1 = A/Ca = A%C,以及k2 = B/Cb = B%C

(k1*C+a) * (k2*C+b)等于(k1*k2*C*C + b*k1*C + a*k2*C + a*b)

如果按C划分,则获得k1*k2*C + b*k1 + a*k2 + (a*b)/C

该数字应保持在16位数的范围内。

在64位计算机上演示该想法的示例程序:

#include <iostream>

int main()
{
   int A = 255;
   int B = 195;
   int C = 200;

   int k1 = A/C;
   int a = A%C;
   int k2 = B/C;
   int b = B%C;

   std::cout << k1*k2*C << std::endl;
   std::cout << k1*b << std::endl;
   std::cout << k2*a << std::endl;
   std::cout << a*b << std::endl;

   int sum = k1*k2*C + k1*b + k2*a + (a*b)/C;
   std::cout << sum << std::endl;
   std::cout << (A*B)/C << std::endl;
}

输出:

0
195
0
10725
248
248