Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/142.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

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
带整数的C++运算给出否定结果_C++_Arduino - Fatal编程技术网

带整数的C++运算给出否定结果

带整数的C++运算给出否定结果,c++,arduino,C++,Arduino,我正在用Arduino调试一个大程序。在某个时候,它开始抛出奇怪的结果,所以我按照它进行了一个不应该给出负数的操作。 结果应该是248625,因为它存储在一个int变量中,给了我相同的-79。我已经尝试过铸造int并应用ceil、floor,但没有成功。 任何帮助都将不胜感激 调试打印: B -> (255*195)/200+0 = -79 守则: // the setup routine runs once when you press reset: void setup() {

我正在用Arduino调试一个大程序。在某个时候,它开始抛出奇怪的结果,所以我按照它进行了一个不应该给出负数的操作。 结果应该是248625,因为它存储在一个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){}
}

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

255 * 195 = -15810   Overflow math:  (-32768 + (49725 - 32767))
-15810 / 200 = -79
您可以通过打印SizeFint来验证整数的大小

在Arduino Uno和其他基于ATMega的板上,int存储 16位2字节值。这将产生-32768到32767的范围 最小值为-2^15,最大值为2^15-1


您可以尝试在Arduino上使用4字节的long。我不一定知道你打算做什么,但这也不可能永远持续下去。您需要处理这样一种情况,即您包装或重置间隔,或者如果它们可以永远增长的话。此外,如果该值不应该变为负值,则可以使用无符号基本数据类型并将其正值范围扩大一倍。

正如其他用户在评论中指出的,这是一个溢出问题。 根据定义,int、long等只有一个固定的最小位数,int的最小位数是16,这就是问题所在。 可能您以前从未遇到过这个问题,因为现在有时int是用32位实现的

要确定每次使用int类型的位数,可以使用以下方法:

typedef int32_t myint;
typedef u_int32_t myuint;
然后只使用myint。通过这种方式,您可以准确地知道所使用的位数,如果您决定根据一些新的需要更改实现,您可以在一个地方进行更改。

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

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

A*B/C=k1*C+A*k2*C+B/C,其中 k1=A/C和A=A%C,k2=B/C和B=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;
}

我相信Arduino int是16位的,所以你能保存的最大值是32767。假设您正在谈论Uno或Mega:您可能需要查找术语整数溢出。简短的版本是,一旦一个整数超过其最大值,它将循环回其可能的最低值,对于16位整数,这意味着32767+1=-32768在这样做时,表达向下投票的点会更文明。如果不是,似乎只有惩罚是选择一个答案而不是自己的答案。塞尔吉奥遗憾地说,在堆栈溢出的C++标签中,你不能真正寻找文明的东西。只是一群人在评论中链接了标准,并对你的问题投了反对票。@Sergio这不是关于内部指针的问题。它只是中间乘法步骤导致49725,这是一个16位整数溢出。下面是一个示例:在这种情况下,这只是使led从0变暗到255值所需的基本操作。光照变化是有步骤的,增量就是差异。在本例中,从0到255。我真的很惊讶我会卷入这件事。由于操作结果必须介于0-255之间,我仍然不明白为什么会出现问题。如果我把一个操作数长一点,那么它就应该执行这个操作,然后我就被迫重铸int。不是吗?”塞尔吉奥考虑使用,一个ARDUINO函数,它的设计恰好是为了达到这个目的而不引起任何数值误差。它还使代码更具可读性。@PatrickTrentin从对主要问题的评论中可以清楚地看出,这是一个简单的int溢出。它不会继续增长,所以map在这种情况下是不合适的。请原谅,但它到底如何不适用?他想把一个值从区间0-200映射到区间0-255,再加上一个偏移量,这正是函数映射的目的。@PatrickTrentin,区别在于a*B超过了16位整数的限制,而其他项则没有。@PatrickTrentin,那么我没有解释为什么我的建议应该有效。取运算中的数字,计算我建议的表达式中的每一项。它们将保持在16位整数的范围内。哦,现在这很清楚了+1:-一开始我不明白你在为整个计算提出一个不同的表达式。>因为Arduino中sizeofint是16,这并不完全正确;sizeof返回字节数,而不是位。
0
195
0
10725
248
248