divide by unsigned long 0 to float conversion

in http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1287692125/17#17 a bug was found due to an division by zero (specifically the unsigned long one) . It seems that print just prints 0.000 then so it is not directly visible while debugging with print statements. I suggest that some remarks are made on http://arduino.cc/en/Reference/Float about this specific condition.

e.g.
Division by zero can cause unpredictable and different results in applications depending on the type of zero (long, int, signed, unsigned etc) .

(edit)
Wrote a test for floats to check for special values. NAN and INFINITY and isnan(), isinf() and isfinite() are defined in math.h.

int testFloat(float f)
{
  if (f == 1/0L)     Serial.println("NaN divide by 0L");
  if (f == 1/0UL)    Serial.println("NaN divide by 0UL");
  if (f == NAN)      Serial.println("NaN");
  if (f == INFINITY) Serial.println("INFINITY");
  if (-f == INFINITY)Serial.println("-INFINITY");
  if (isnan(f))      Serial.println("isnan");
  if (isinf(f))      Serial.println("isinf");
  if (isfinite(f))   Serial.println("isfinite = OK");
  return 0;
}

Think this can be used to extend the printFloat() function in hardware\arduino\cores\arduino\Print.cpp

Rob

This seems highly useful, and what I think would be really awesome is if it were combined with the printFloat function in the playground that does formatting, into a function that returns a string instead of printing directly to serial, for better flexibility. So it would look something like

String sprintFloat(const float& value, int length)

And you'd need some minimum length override, maybe 3 or 4, to fit in stuff like NaN.

I'm kind of surprised a function like this that takes any numeric data type isn't already built into Arduino. So much debugging time spent assuming that '0.00' really means 0.00 when it doesn't...
I may do this when I have free time, which may be in late January.

I suggest that some remarks are made on http://arduino.cc/en/Reference/Float about this specific condition.

I strongly disagree.

You are trying to define "correct behavior" for an operation that on any other system would throw an exception.

The correct thing to do when dividing by 0 is to not do it.

You are trying to define "correct behavior" for an operation that on any other system would throw an exception.

While it's true that these conditions should be avoided, I understand the frustration of not having exceptions thrown, which would greatly aid in debugging.

I'm not sure what the 'correct behavior' is that robtillart is trying to define. I do see the point that one should not divide by a number and then check to see if the result is reasonable, rather than check to ensure the divisor is nonzero.

Absent exceptions, and given that the isnan() etc. functions provided in the Arduino library don't capture all the divide-by-zero scenarios, what would be your suggestion of a good debugging tool to catch divide-by-zeros etc. a few operations downstream?

what would be your suggestion of a good debugging tool to catch divide-by-zeros etc. a few operations downstream?

The fundamental (and incorrect) assumption in this statement is that it is possible to catch the error sometime after it occurs.

The division operation returns a result. As soon as it returns, it is done and any history of what it did (or did not do) is lost.

You can not look at the result of the division operation and make any conclusions about where it came from.

The question is like saying "I have a plate of scrambled eggs. How can I tell if there was a mark on the shell of the egg used to make this bit of my plate of scrambled eggs".

If you don't want scrambled eggs made from eggs with marks on the shell, you must tell the cook that before the cook begins breaking eggs.

Think this can be used to extend the printFloat() function in hardware\arduino\cores\arduino\Print.cpp

Thumbs up for this one. It would be a useful extension.

I have to agree with PaulS on this one.
It isn't right to depend on the print function, or any other one, to catch a division-by-zero, you should do this before you even divide.

It isn't right to depend on the print function, or any other one, to catch a division-by-zero

I may agree to that as well.

The proposal however is to print a correct representation of the number passed to the print float function. Currently 0 gets printed when the number is invalid or infinite.

I don't think anyone would argue that Microsoft should modify Excel so that 0 gets printed when you overflow or divide by zero.

On a prototyping platform such as Arduino, this would be a handy feature during debugging.

The proposal however is to print a correct representation of the number passed to the print float function. Currently 0 gets printed when the number is invalid or infinite.

I couldn't have formulated it better. Thanks Ben

Ah, my bad, I thought the issue was a bit different.
Though I do wonder...

Currently 0 gets printed when the number is invalid or infinite.

To be honest, I do think 0 would be the correct error value in this case, as it equates to a false in comparison operators. Since it is an undetermined value, the most likely value to halt the program would be the most logical one.. since exceptions aren't there.

Still, I have to keep on agreeing with PaulS.

to catch the error sometime after it occurs.

If I understand correctly now, you want the print function to correctly represent the invalid or infinite value. Since the controller can't save such a value, or a flag for such a value (as PaulS pointed out with the above quote), there is no way for the print function to know that the returned value isn't actually 0.

So I wonder what you would like to see?
If I had to design the behaviour for this scenario, I have to admit that I probably would've done a similiar thing.. and make it return 0 in case of a invalid value or a division by zero.

So I wonder what you would like to see?
If I had to design the behaviour for this scenario, I have to admit that I probably would've done a similiar thing.. and make it return 0 in case of a invalid value or a division by zero.

I would like to see a string representation of 'undefined'. NaN or a similar convention would be great.

I don't understand the idea that printing 0.00 is correct in any sense. The mathematical value is not zero, and the bit representation is invalid and can be detected to be invalid (assuming the originally posted function works as advertised). Printing zero adds numerous incorrect candidate reasons for seeing a zero that the programmer really shouldn't have to eliminate in order to know that a divide by zero is his or her real problem.

The more I think about it the more misleading printing '0.00' seems when the value is anything other than 0.00. Even a blank space or empty string would be more informative and therefore more 'correct'.

Since the controller can't save such a value, or a flag for such a value (as PaulS pointed out with the above quote), there is no way for the print function to know that the returned value isn't actually 0.

I trust the above is written with the best of intentions, but it is nevertheless wrong from start to finish.

The two values NaN and InF are well defined for IEEE 754 (single precision float data type) and equally distinguishable from other values as 0 is from 1. Also the conditions that lead to these results are defined and highly predictable.

Print does not alter these two special values or any other value in any way whatsoever, nor does it return any value back to the caller. In fact it is completely neutral when it comes to program flow, program logic and calculations as well as where, when and how the value came to be. Its only task is to give an honest visual representation of the value passed to it for printing. This is not the case for NaN and InF and the proposal is to correct this behavior.

So I wonder what you would like to see?

As Ben pointed out there are three additional values I would like to see represented correctly by print.

  1. NaN = Not A Number
  2. INF = Infinite (positive and the negative one)

INF values are caused by overflow e.g "big + big == too big". The sign is significant.

NaN can be caused by :

 + :  +[ch8734]  +  [ch8722][ch8734].
 x :  0 x  [ch8734].
 / :  /0 including 0/0,  or  [ch8734]/[ch8734].
 % :  x % 0   or  [ch8734] % x .
 f() :  sqrt(a)  a<0, log(x) x<=0, tan(pi/2 +k.pi)

As Paul points out you should not divide by zero, especially if you know it will happen. He is 100% right, just as he is right that you should not do all those other things that causes a NaN condition. You could prevent them from happening and that is called defensive programming, which results in more robust but slower and bigger and far complexer programs. Be aware that the additional defensive code must be robust too, so simply preventing an addition overflow by testing a subtraction is not good enough as how do you prevent a subtraction underflow in the test in the first place?

There are many application in which defensive programming is a must e.g. medical devices. Most apps made for Arduino are not as critical as a those. In the end it is a design decision to use it or not (just as it is that printFloat() will print NaN as 0).

O yes, more about NaN - NotANumber can be found on - IEEE 754-2008 revision - Wikipedia

The more I think about it the more misleading printing '0.00' seems when the value is anything other than 0.00. Even a blank space or empty string would be more informative and therefore more 'correct'.

This issue isn't in what gets printed. The issue is what is returned by the n/0 operation. The / operator needs to return a value. When n is a float, the value that it returns needs to be a float.

What you would need to do it change what the / operator returns when the operation is invalid. Printing is completely beside the point.

If the / operator chooses to return 0 when the operation is not possible, there is no way for the print function to print anything other than 0.00, and I sure as heck don't want it to even try.

By the time print is called, the value that it is called for is a float. Plain and simple. The print function has no way of knowing that at some point an invalid operation was used in generating the value at the memory location it is being asked to print the value in.

Here's a proposed patch to "Print.cpp" based on 021. This mod will catch NaN's as well as positive and negative infinity (an alternative might be a combined test for NaN/InF and printing of a single character such as '*').

void Print::printFloat(double number, uint8_t digits) 
{ 
  // check for invalid number
  if (isnan(number)) {
     print("NaN");
     return;
  }

  // Handle negative numbers
  if (number < 0.0)
  {
     print('-');
     number = -number;
  }

  // check for infinity
  if (isinf(number)) {
    print("InF");
    return;
  }

  // Round correctly so that print(1.999, 2) prints as "2.00"
  double rounding = 0.5;
  for (uint8_t i=0; i<digits; ++i)
    rounding /= 10.0;
  
  number += rounding;

  // Extract the integer part of the number and print it
  unsigned long int_part = (unsigned long)number;
  double remainder = number - (double)int_part;
  print(int_part);

  // Print the decimal point, but only if there are digits beyond
  if (digits > 0)
    print('.'); 

  // Extract digits from the remainder one at a time
  while (digits-- > 0)
  {
    remainder *= 10.0;
    int toPrint = int(remainder);
    print(toPrint);
    remainder -= toPrint; 
  } 
}

Yes....

But again, nothing is returned from the division that could be checked to see whether it is NaN or INF.
How do you propose to alter the division operator so that it returns the resulting value AND a flag whether or not it is NaN or INF?

But again, nothing is returned from the division that could be checked to see whether it is NaN or INF.

Are you certain?

How do you propose to alter the division operator so that it returns the resulting value AND a flag whether or not it is NaN or INF?

IEEE floating-point format provides for infinite and not-a-number. If the GCC-AVR library complies with the standard, then the division operator needs no change.

I suggest you give it a try...

void setup( void )
{
  Serial.begin( 115200 );
  Serial.println( "\r\n\r\n\r\n\r\n" );
  
  float a, b, c;
  a = 37.1487;
  b = 0.0;
  c = a / b;
  
  if ( isnan( c ) )
  {
    Serial.println( "NaN" );
  }
  
  if ( isinf( c ) )
  {
    Serial.println( "InF" );
  }
}

void loop( void )
{
}

I stand corrected, assuming that arduino indeed adheres to the standard.

Print should indeed be able to print the NaN and INF representations for floats.