# math expressions within abs()

I am trying to port a program from Perl to Arduino C. In the manual I found that math expressions within abs() are discouraged. My current Perl code does a abs(\$var-1). How could I do this the best way on the Arduino (without changing the value of var) if abs(var-1) does not work?

Reiner.

I don't know about discouraging math within abs I would just directly translate from Perl. Is \$var a string in Perl or a regular number? I don't believe Perl distinguishes integers and floats but you need to define int or float in Arduino C.

Warning

Because of the way the abs() function is implemented, avoid using other functions inside the brackets, it may lead to incorrect results.

Try this:

``````tmp = var - 1;
abs(tmp)
``````

In http://arduino.cc/en/Reference/Abs it says:

Warning

Because of the way the abs() function is implemented, avoid using other functions inside the brackets, it may lead to incorrect results.

abs(a++); // avoid this - yields incorrect results

a++; // use this instead -
abs(a); // keep other math outside the function

That's what made me think that I need to do it differently. But if this is not the case, then I will happily use the direct equivalent abs(var-1). And yes, \$var can be a string or an integer in Perl. I have defined it as a int in my Arduino code.

If the abs(x) function is defined as macro you can have side effects

#define abs(x) (((x) >= 0) ? (x) : (-(x))) // Note the amount of ()'s ...

if you code: y = abs(a++) ; the a++ will be executes at least twice (left as an exercise for the reader)

You can always do
y=\$var-1 and then abs(y) to be sure. The following from the reference page is just strange:

abs(a++); // avoid this - yields incorrect results

a++; // use this instead -
abs(a); // keep other math outside the function

Maybe the person that wrote the above didn't know what a++ is supposed to do. If he wants a to increment before the abs, he should use abs(++a).

If abs() is a function, then its parameter is parsed and calculated before the function call is made. End of the story. If the abs() is a macro, it may mess up a little if written improperly.

You beat me to it on "macro messes things up", Rob.

I never use macro defs like that. It's just a poor way to construct things with unpredictable outcomes. Always use a function so its parameters get evaluated before the call.

@liudr
Robustness is one thing speed another, it is difficult to optimize both. A function takes the calling overhead and has a parameter and return type.

That said - why not just code the abs() directly as it takes minimal lines

// y = abs(a++);
a++;
if (a > = 0) y = a;
else y = -a;

I think in my case it will be the best if I use the version with the temporary variable - even though this looks ugly to me Coding the abs manually would not help here since I want the original variable "var" untouched and not modify it like in the a++ example.

Sans side-effects.

``````#define abs(x) ({__typeof__(x)__x=(x);__x<0?-__x:__x;})
``````

AWOL:
Sans side-effects.

``````#define abs(x) ({__typeof__(x)__x=(x);__x<0?-__x:__x;})
``````

Thanks for digging it up from arduino ?? file. I’ll be cautious myself when using the function then.