首页 > 解决方案 > Why does division in #define cause division in code to output a different answer

问题描述

I was getting speed values 4 times less than I calculated and narrowed it down to the division of the inverse of the wheel radius. I originally had WHEEL_D_OVER_TWO and when doing the reciprocal I was getting an incorrect answer(a factor of 4 difference). I have replicated the problem in the code below.

Hardware is an Arduino UNO.

#define WHEEL_RADIUS 30.0
#define WHEEL_D_OVER_TWO 60.0 / 2.0

void setup() { Serial.begin(115200); }

void loop() {
  Serial.println("WHEEL_RADIUS : " + String(WHEEL_RADIUS, 8));
  Serial.println("Inverse WHEEL_RADIUS : " + String(1.000 / WHEEL_RADIUS, 8));
  Serial.println("WHEEL_D_OVER_TWO : " + String(WHEEL_D_OVER_TWO, 8));
  Serial.println("Inverse WHEEL_D_OVER_TWO : " +
                 String(1.000 / WHEEL_D_OVER_TWO, 8));
  delay(1000);
}

The output of the above code is

WHEEL_RADIUS : 30.00000000
Inverse WHEEL_RADIUS : 0.03333334
WHEEL_D_OVER_TWO : 30.00000000
Inverse WHEEL_D_OVER_TWO : 0.00833333

Inverse WHEEL_RADIUS is correct using a calculator. Most problems I searched for were for integer division which I think I am avoiding here. I know the current workaround but I would like to know what I am fundamentally missing from this example that is giving me different answers.

Thanks in advance.

标签: arduino

解决方案


宏只是文本替换。你WHEEL_D_OVER_TWO的定义为

#define WHEEL_D_OVER_TWO 60.0 / 2.0

意思就是

1.000 / WHEEL_D_OVER_TWO

扩展到

1.000 / 60.0 / 2.0

由于/C 和 C++ 中的运算符从左到右关联,因此这被解释为

(1.000 / 60.0) / 2.0

显然,这甚至与

 1.000 / WHEEL_RADIUS

(这显然是你所期望的)。

这就是为什么当你将宏定义为表达式时,记住给它们加上括号很重要

#define WHEEL_D_OVER_TWO (60.0 / 2.0)

这将使您免于这样的惊喜。

一个更好的主意(至少在 C++ 中)是使用const变量而不是宏并完全忘记这个问题

const double WHEEL_D_OVER_TWO = 60.0 / 2.0;

推荐阅读