arduino.绝对值函数发现其参数的大小。
一个例子是测量机器人的速度。假设一个人
车轮的附着具有定向编码器。旋转
光学编码光盘,返回正向运动的正值和
向后运动的负值。
你不'要只有负速度速度速度值或绝对值。
speed = abs(registic_encoder_delta_change_over_time);
arduino.绝对值宏是:
#define abs(x) ((x)>0?(x):-(x))
这将适用于任何类型的类型。
在C代码中,绝对值操作是一个函数。
int abs( int x );
事实上,在C中,ABS功能仅定义为在整数值上工作。
在C ++中,通常存在过度的ABS来处理浮点和其他类型(检查文档)。
宏的问题是他们展开代码,不起作用
对于所有案例。它们对于单个元素变量或常数很好
如果在宏的参数中放置多操作,则会出现值。
这里'S正确工作的Arduino绝对值的插图:
x = abs(-5);
Result x is 5.
int a = -5;
x = abs(a);
Result x is 5.
float fv = -45.22
x = abs(fv);
Result x is 45.22.
这里'arduino绝对值宏失败的位置:
a = -5;
x = abs(a++);
Result x is 4 <<<< ERROR
Serial.print("a after");Serial.println(a);
Result x is -3 <<<< ERROR
事实上,你期望得到的结果是5和价值'a' after the "function call"应该-4但是它是-3。
代码似乎显示了正确的动作,但是当你写一个"normal"
C代码后增量操作员应该在此处生效
操作结束,而不是开始。这里它已经执行了++
开始。原因是宏被扩展为不同的c
代码比你召唤函数 - 没有函数 - 没有调用函数。
允许将宏ABS()与ABS的功能版本进行比较。我在这'在IABS()中重新创建它:
INIAB(int x){return x<0 ? -x : x; }
此示例在参数中使用多操作。这里它是递增参数变量的post。
a = -5;
x = Iabs(a++);
Result x is 5 <<<< CORRECT
Serial.println(a);
Result a is -4 <<<< CORRECT
要了解为什么会发生这种情况,您需要扩展宏:
宏是:
#define abs(x) ((x)>0?(x):-(x))
随着编译器展开它
a = -5;
x = abs(a ++);被替换为:
((a++)>0?(a++):-(a++))
两次变量'a' can be incremented:
如果将函数放入ABS()宏的参数,则会发生同样的问题。它将被调用两次!
随时您放置以外的任何常量或变量
进入Arduino绝对值宏,它会出乎意料
results (see above).
这意味着为Arduino C / C ++编写的代码可能无法在其他方面工作
编译器,因为您可能需要浮点的绝对值
输入.ino文件,但这会导致另一个编译器中的错误
因为标准版本仅为整数编写。
此外,如上所示,Arduino绝对值宏执行
论证两次导致更严重的问题 - 因为它们发生在运行时
时间(共同组织者不会为您抱怨!)。
尽管ABS的功能版本不是更好地工作
反复执行参数有一个其他问题。
即当您使用整数和整数数学时,它将返回
错误的价值。在不同的编译器中也可能不同
(取决于实施)。
这是由于两者'创建正数和负数的补充方法。
当您使用极值(inttypes.h中定义的int16_min)时,它将返回错误的事情:
考虑
a = -32768;
x = Iabs(a)
结果x为-32768<<<< ERROR
这个 GNU文档 表示当INT_MIN用作IABS()的输入时,输出未定义。
您可以使用它并避免极值或检测最小值并输出最大值:
int _abs(int x){
if (x == INT16_MIN)
return INT16_MAX;
else
return x<0 ? -x : x;
}
现在
a = -32768;
x = _abs(a)
Result x is 32767 <<<< NEARLY CORRECT
然而,因为两种方式'S补充工作,纠正
int16_min的Arduino绝对值(-32768)将返回32767.但是在
至少它与你想要的相反,这是一个人。它只是1
value out.
它看起来像Arduino Mega,ESP8266和ESP32实现使用
使用函数而不是宏的标准实现所以请注意
有区别!它被描述为不使用浮动
所以这个功能只为这些芯片!
资源: //forum.arduino.cc/index.php?topic=626297.0
它是标准C库的一部分'normal' compilers you
必须添加包含指令以启用其使用:
#include <stdlib.h>
arduino. 环境通过扫描代码中的已知函数来使其更容易 并自动包括相关标题文件(所以你不'T需要上面的线)。
什么时候
处理他们将要的不同公司使用的微控制器
经常使用有自己编译器的芯片,所以您需要它
#include否则编译器会抱怨。因为它是这样的
常用功能它是定义的
stdlib.h - 标准库头文件。
在 t Iabs(在 t x) { return x<0 ? -x : x; }
在 t _abs(在 t x) {
if (x == INT16_MIN)
return INT16_MAX;
别的
return x<0 ? -x : x;
}
void setup() {
Serial.begin(115200);
Serial.println("abs() test");
Serial.println("\nTest P 1.1 abs macro of a constant. value -5 ");
Serial.print("abs(-5) = "); Serial.println( abs(-5) );
Serial.print("\nTest P 1.2. abs macro of an integer. a = ");
在 t a = -5;
Serial.println( a );
Serial.print("abs(a) = "); Serial.println( abs(a) );
Serial.print("\nTest P 1.3. abs macro of a float. fv = ");
float fv = -45.22;
Serial.println( fv );
Serial.print("abs(fv) = "); Serial.println( abs(fv) );
Serial.print("\nTest F 2.1. abs macro extra operation (FAIL). a = ");
a = -5;
Serial.println( a );
Serial.print("abs(a++) = ");Serial.println( abs(a++) );
Serial.print("a after = ");Serial.println(a);
Serial.print("\nTest F 2.2. abs fn extra operation (PASS). a = ");
a = -5;
Serial.println( a );
Serial.print("Iabs(a++) = ");Serial.println( Iabs(a++) );
Serial.print("a after = ");Serial.println(a);
Serial.print("\nTest F 4.1. does fabs work? fv= ");
fv = -45.22;
Serial.println( fv );
Serial.print("fabs(fv) = ");Serial.println( fabs(fv) );
Serial.print("\nTest F 4.2. does labs work? fv= ");
long lv = -32123213123L;
Serial.println( lv );
Serial.print("labs(lv) = ");Serial.println( labs(lv) );
/////////////////////////////// LONG
Serial.print("\n==================== LONG");
Serial.println("\nTest F 4.0. 32 bit min max ");
Serial.println( INT32_MIN );
Serial.println( INT32_MAX );
Serial.print("\nTest F 4.3. extreme values a =(INT32_MIN+1) = ");
Serial.println(INT32_MIN+1);
lv = INT32_MIN+1;
Serial.print("labs(a) = ");Serial.println( labs(lv) );
Serial.print("\nTest F 4.4. extreme values INT32_MIN = ");
Serial.println(INT32_MIN);
lv = INT32_MIN;
Serial.print("labs(a) = ");Serial.println( labs(lv) );
///////////////////////////// INT
Serial.println("\n==================== INT");
Serial.print("\nTest F 4.0. 16 bit min max ");
Serial.println( INT16_MIN );
Serial.println( INT16_MAX );
Serial.print("\nTest F 3.1. extreme values a =(INT16_MIN+1) = ");
Serial.println(INT16_MIN+1);
a = INT16_MIN+1;
Serial.print("Iabs(a) = ");Serial.println( Iabs(a) );
Serial.print("\nTest F 3.2. extreme values INT16_MIN = ");
Serial.println(INT16_MIN);
a = INT16_MIN;
Serial.print("Iabs(a) = ");Serial.println( Iabs(a) );
///////////////////////////// new abs
Serial.println("\n==================== new abs");
Serial.print("\nTest F 5.1. extreme values INT16_MIN = ");
Serial.println(INT16_MIN);
a = INT16_MIN;
Serial.print("_abs(a) = ");Serial.println( _abs(a) );
}
void loop() {
// put your main code here, to run repeatedly:
}
abs() test Test P 1.1 abs macro of a constant. value -5 abs(-5) = 5 Test P 1.2. abs macro of an integer. a = -5 abs(a) = 5 Test P 1.3. abs macro of a float. fv = -5.22 abs(fv) = 45.⸮abs() test Test P 1.1 abs macro of a constant. value -5 abs(-5) = 5 Test P 1.2. abs macro of an integer. a = -5 abs(a) = 5 Test P 1.3. abs macro of a float. fv = -45.22 abs(fv) = 45.22 Test F 2.1. abs macro extra operation (FAIL). a = -5 abs(a++) = 4 a after = -3 Test F 2.2. abs fn extra operation (PASS). a = -5 Iabs(a++) = 5 a after = -4 Test F 4.1. does fabs work? fv= -45.22 fabs(fv) = 45.22 Test F 4.2. does labs work? fv= -2058442051 labs(lv) = 2058442051 ==================== LONG Test F 4.0. 32 bit min max -2147483648 2147483647 Test F 4.3. extreme values a =(INT32_MIN+1) = -2147483647 labs(a) = 2147483647 Test F 4.4. extreme values INT32_MIN = -2147483648 labs(a) = -2147483648 ==================== INT Test F 4.0. 16 bit min max -32768 32767 Test F 3.1. extreme values a =(INT16_MIN+1) = -32767 Iabs(a) = 32767 Test F 3.2. extreme values INT16_MIN = -32768 Iabs(a) = -32768 ==================== new abs Test F 5.1. extreme values INT16_MIN = -32768 _abs(a) = 32767
arduino.绝对值abs()的Arduino版本是宏:
优点
缺点
使用ADS1115精度16位ADC进行教程进行低功耗。
arduino.模拟输出:如何创建最精确的PWM模拟输出以及如何创建模拟PWM正弦波。
了解DigitalWrite()的工作原理......现在使用17倍宏宏!
如何使用TCS230(/ TCS3200)彩色检测器芯片并轻松将其添加到您的任何项目中。
使用ADXL345 Acellerometer,您可以检测到16G!您还可以了解如何使用它来点击检测等。
HMC5883L - 如何制作数字罗盘,了解HMC5883L和QMC5883L之间的差异以及它们是否兼容。
新的! Comments
让你说到你刚刚阅读的东西!留下下面的框中的评论。