成为订阅者(免费)

加入29,000名其他订阅者以获得用户销售折扣和 其他免费资源。
:
:
大学教师'担心 - 您的邮件地址完全是 安全的。我保证使用它 只要 to send you MicroZine.

arduino.绝对值


arduino.绝对值函数发现其参数的大小。

它真的只返回任何输入值(负或正面)的正值。数学是:

    x = |x|

如果x = 300那么| 300 | = 300,或ABS(300)== 300
如果x = -300然后| -300 | = 300,
或ABS(-300)== 300

那'S都很好,简单,但魔鬼在细节中!

用法例子

一个例子是测量机器人的速度。假设一个人 车轮的附着具有定向编码器。旋转 光学编码光盘,返回正向运动的正值和 向后运动的负值。

你不'要只有负速度速度速度值或绝对值。

    speed = abs(registic_encoder_delta_change_over_time);

ABS()定义如何?

arduino.绝对值宏是:

    #define abs(x) ((x)>0?(x):-(x))

这将适用于任何类型的类型。

在C代码中,绝对值操作是一个函数。

    int abs( int x );

事实上,在C中,ABS功能仅定义为在整数值上工作。

警告: arduino.将ABS()与C环境不同。

在C ++中,通常存在过度的ABS来处理浮点和其他类型(检查文档)。

笔记: 其他功能:Fabs,Labs和Llabs for float,长,长长。

什么's the problem?

宏的问题是他们展开代码,不起作用 对于所有案例。它们对于单个元素变量或常数很好 如果在宏的参数中放置多操作,则会出现值。

这里's abs()宏工作正常

这里'S正确工作的Arduino绝对值的插图:

1.1。 Arduino绝对值的常数:

    x = abs(-5);

    Result x is 5.

1.2。 Arduino Integer变量的绝对值:

    int a = -5;

    x = abs(a);

    Result x is 5.

1.3。浮动变量的Arduino绝对值:

    float fv = -45.22

    x = abs(fv);

    Result x is 45.22.

这里's abs()宏失败

这里'arduino绝对值宏失败的位置:

2.1。宏中的额外操作

    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()中重新创建它:

功能定义IABS.

    INIAB(int x){return x<0 ? -x : x; }

2.2。 ABS功能内的额外操作

此示例在参数中使用多操作。这里它是递增参数变量的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:

  1. 一旦处于条件(最左边的括号)。
  2. 一次在其中一个选定的结果(最右边的括号之一)。
警告: 仅针对单个变量使用ABS宏,无操作。

如果将函数放入ABS()宏的参数,则会发生同样的问题。它将被调用两次!

ABS()的问题

arduino.绝对值宏的问题

随时您放置以外的任何常量或变量 进入Arduino绝对值宏,它会出乎意料 results (see above).

这意味着为Arduino C / C ++编写的代码可能无法在其他方面工作 编译器,因为您可能需要浮点的绝对值 输入.ino文件,但这会导致另一个编译器中的错误 因为标准版本仅为整数编写。

此外,如上所示,Arduino绝对值宏执行 论证两次导致更严重的问题 - 因为它们发生在运行时 时间(共同组织者不会为您抱怨!)。

arduino.绝对值函数的问题

尽管ABS的功能版本不是更好地工作 反复执行参数有一个其他问题。 即当您使用整数和整数数学时,它将返回 错误的价值。在不同的编译器中也可能不同 (取决于实施)。

这是由于两者'创建正数和负数的补充方法。

当您使用极值(inttypes.h中定义的int16_min)时,它将返回错误的事情:

考虑

    a = -32768;

    x = Iabs(a)
       
        结果x为-32768<<<< ERROR

提示: 一个类似的问题是在Labs()中作为两个'也使用了补充。

这个 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实施方式

它看起来像Arduino Mega,ESP8266和ESP32实现使用 使用函数而不是宏的标准实现所以请注意 有区别!它被描述为不使用浮动 所以这个功能只为这些芯片!

资源: //forum.arduino.cc/index.php?topic=626297.0

使用ABS在其他编译器中

它是标准C库的一部分'normal' compilers you 必须添加包含指令以启用其使用:

    #include <stdlib.h>

arduino. 环境通过扫描代码中的已知函数来使其更容易 并自动包括相关标题文件(所以你不'T需要上面的线)。

什么时候 处理他们将要的不同公司使用的微控制器 经常使用有自己编译器的芯片,所以您需要它 #include否则编译器会抱怨。因为它是这样的 常用功能它是定义的 stdlib.h - 标准库头文件。

arduino.绝对值测试草图

以下代码示例通过各种ABS选项,并显示如上所述的问题。

在 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:

}

素描输出

在Arduino Uno上的此草图的输出是:

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版本是宏:

优点

  • 快速(无函数调用的开销)。
  • 可以接受任何类型的值(并返回相同类型)。

缺点

  • 如果使用多操作或功能,会出错。
  • 与标准C编程不一致。



新的! Comments

让你说到你刚刚阅读的东西!留下下面的框中的评论。




隐私政策 | 接触 | 关于我

网站地图 | 使用条款


ezoic.报告此广告

访问我们的Facebook页面:

   点击这里



最近的文章

  1. 如何使用ADS1115

    使用ADS1115精度16位ADC进行教程进行低功耗。

    阅读更多

  2. arduino.模拟输出...易模拟输出生成

    arduino.模拟输出:如何创建最精确的PWM模拟输出以及如何创建模拟PWM正弦波。

    阅读更多

  3. 数号和等效的快速宏。加快代码!

    了解DigitalWrite()的工作原理......现在使用17倍宏宏!

    阅读更多

  4. TCS230颜色传感芯片:如何运作以及如何使用它。

    如何使用TCS230(/ TCS3200)彩色检测器芯片并轻松将其添加到您的任何项目中。

    阅读更多

  5. 如何使用ADXL345进行运动感测等。

    使用ADXL345 Acellerometer,您可以检测到16G!您还可以了解如何使用它来点击检测等。

    阅读更多

  6. HMC5883L 3轴数字MAGENTOMTER如何运作

    HMC5883L - 如何制作数字罗盘,了解HMC5883L和QMC5883L之间的差异以及它们是否兼容。

    阅读更多



读者 Comments

"I wanted to thank
你这么好
对于所有信息
你已经提供了
你的网站's

高超极好的."

- 逃亡Potthath.

"This site really is
最好的和我最喜欢的。
我发现这里有很多很有用
项目和提示。"

- 米兰

Bursach.<at>gmail.com<

"Awesome site,
非常,非常容易和好
导航!"


-
镭_tr.<at>
wolf359.cjb.net.


学习微控制器

"Interested in
微控制器?"

注册
免费7天指南:

自由 GUIDE : CLICK HERE


"I am a newbie to PIC
我想说
 how great your
网站一直在为我。"


- 戴夫

de_scott.<at>bellsouth.net

"Your site is a great
和完美的工作。
恭喜。"


- SURESH.

IntegratedInfosys.<at>
Yahoo.com.

"I couldn't find the correct
要定义的词语
你的网页。

非常有用,揭开,
诚实明确。

非常感谢
你的时间和作品。
问候。"


- Anon.

回到顶部