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.

@ http://arduino.cc/en/Reference/Abs

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 :slight_smile: 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.