Why does log10(-d.d) return zero

This took me forever to figure out. I was measuring a digits length with log10 to be able to init a char array to the correct size for dtostrf when a bug that allowed negative numbers to reach the log10 function. This caused the arduino to reset whether from array bounds checking(doubt it. anybody know?), overwriting executable or whatever. This is all because the log10 function on from avr-libc returns 0 for negative numbers where as a handheld calculator and an x86 c program return errors or indeterminate. Why does log10 return zero for negative input? Seems all it does is cause problems and make debugging harder than it should be. A google search seems to turn up nothing and the avr-libc page for log10 doesn't have anything on it. If nobody knows or this question can only be answered by the person(s) who made avr-libc, then let this post be a reference for everybody else.

It's pretty simple - as a function, SOMETHING has to be returned - and seeing as there isn't a place for run-time error handling / exception handling, and your variable isn't defined until runtime, thus invalidating compile-time checks, it just silently fails. Admittedly, returning NaN would be nice - or it might actually be returning NaN, and the #define for NaN is set to 0.

infomaniac50:
This is all because the log10 function on from avr-libc returns 0 for negative numbers where as a handheld calculator and an x86 c program return errors or indeterminate. Why does log10 return zero for negative input?

log10 is defined as such:

extern double log10(double __x) __ATTR_CONST__;

Thus whatever it returns has to be a "double". There is no "error" or "indeterminate" return. This isn't a calculator.

According to "man log10":

log1p(-1) returns -infinity and raises the "divide-by-zero" floating-point exception.

However exceptions are not enabled on the Arduino platform.

Actually it returns NAN (not a number) as this proves:

void setup ()
{
  
  double x = log10 (-1);
  Serial.begin (115200);
  Serial.println (x);
  Serial.println (isinf (x));
  Serial.println (isnan (x));
  Serial.println (isnan (0));
}

void loop () {}

Output:

0.00
0
1   <--- is nan for log10 (-1)
0

So the bug is really that you are not testing for isnan on the result.

Or try this:

void setup ()
{
  double x = log10 (-1);
  Serial.begin (115200);
  Serial.println (x == 0);
}

void loop () {}

That prints "0".

So your report that "the log10 function on from avr-libc returns 0 for negative numbers" isn't correct. It did not return zero.

I probably got zero because I wanted a quick way to print the value so I just casted to an int for debugging. Its nice to know that it actually returns nan. I was casting to int in my print float function when getting the length of the digit with log10. So nan casted to int returns zero I guess. Anyway I just used abs before the log10 function.