When does N divided by zero not equal N divided by zero?
When the result is a long or unsigned long, and N is not an unsigned long, and zero is not an unsigned long.
If the result is a byte, int or unsigned int, it doesn't matter what type N or zero are, the results are always the same, but when the result is an unsigned long or a long, the type of the denominator affects what the result will be.
I have written a series of macros and functions which manage to divide expeditiously, however for divide by zero, it doesn't always return the correct result, and I can't figure out how to get the correct result.
I think I need to know the type of the variable (unsigned int versus int, for example) in order to return the correct result.
Here's my code, followed by the results.
Note: divide0_sizeX is my attempt at returning the right value, but it fails with almost the same frequency as does just returning 0xFFFFFFFF.
#define divide0( numerator ) ( numerator / 0 )
byte byte_numerator = 12 ;
byte byte_denominator = 0 ;
int int_numerator = 12 ;
int int_denominator = 0 ;
unsigned int unsigned_int_numerator = 12 ;
unsigned int unsigned_int_denominator = 0 ;
long long_numerator = 12 ;
long long_denominator = 0 ;
long long_result = 0 ;
unsigned long unsigned_long_numerator = 12 ;
unsigned long unsigned_long_denominator = 0 ;
//=======================================================================================
Serial.print(F("ulong byte byte "));
long_result = byte_numerator / byte_denominator ;
Serial.print(long_result,HEX);
Serial.print(F(" "));
long_result = divide0( byte_numerator ) ;
Serial.print(long_result,HEX);
Serial.println();
Serial.print(F("ulong byte int "));
long_result = byte_numerator / int_denominator ;
Serial.print(long_result,HEX);
Serial.print(F(" "));
long_result = divide0( byte_numerator ) ;
Serial.print(long_result,HEX);
Serial.println();
Serial.print(F("ulong byte uint "));
long_result = byte_numerator / unsigned_int_denominator ;
Serial.print(long_result,HEX);
Serial.print(F(" "));
long_result = divide0( byte_numerator ) ;
Serial.print(long_result,HEX);
Serial.println();
Serial.print(F("ulong byte long "));
long_result = byte_numerator / long_denominator ;
Serial.print(long_result,HEX);
Serial.print(F(" "));
long_result = divide0( byte_numerator ) ;
Serial.print(long_result,HEX);
Serial.println();
Serial.print(F("ulong byte ulong "));
long_result = byte_numerator / unsigned_long_denominator ;
Serial.print(long_result,HEX);
Serial.print(F(" "));
long_result = divide0( byte_numerator ) ;
Serial.print(long_result,HEX);
Serial.println();
Serial.print(F("ulong int byte "));
long_result = int_numerator / byte_denominator ;
Serial.print(long_result,HEX);
Serial.print(F(" "));
long_result = divide0( int_numerator ) ;
Serial.print(long_result,HEX);
Serial.println();
Serial.print(F("ulong int int "));
long_result = int_numerator / int_denominator ;
Serial.print(long_result,HEX);
Serial.print(F(" "));
long_result = divide0( int_numerator ) ;
Serial.print(long_result,HEX);
Serial.println();
Serial.print(F("ulong int uint "));
long_result = int_numerator / unsigned_int_denominator ;
Serial.print(long_result,HEX);
Serial.print(F(" "));
long_result = divide0( int_numerator ) ;
Serial.print(long_result,HEX);
Serial.println();
Serial.print(F("ulong int long "));
long_result = int_numerator / long_denominator ;
Serial.print(long_result,HEX);
Serial.print(F(" "));
long_result = divide0( int_numerator ) ;
Serial.print(long_result,HEX);
Serial.println();
Serial.print(F("ulong int ulong "));
long_result = int_numerator / unsigned_long_denominator ;
Serial.print(long_result,HEX);
Serial.print(F(" "));
long_result = divide0( int_numerator ) ;
Serial.print(long_result,HEX);
Serial.println();
Serial.print(F("ulong long byte "));
long_result = long_numerator / byte_denominator ;
Serial.print(long_result,HEX);
Serial.print(F(" "));
long_result = divide0( long_numerator ) ;
Serial.print(long_result,HEX);
Serial.println();
Serial.print(F("ulong long int "));
long_result = long_numerator / int_denominator ;
Serial.print(long_result,HEX);
Serial.print(F(" "));
long_result = divide0( long_numerator ) ;
Serial.print(long_result,HEX);
Serial.println();
Serial.print(F("ulong long uint "));
long_result = long_numerator / unsigned_int_denominator ;
Serial.print(long_result,HEX);
Serial.print(F(" "));
long_result = divide0( long_numerator ) ;
Serial.print(long_result,HEX);
Serial.println();
Serial.print(F("ulong long long "));
long_result = long_numerator / long_denominator ;
Serial.print(long_result,HEX);
Serial.print(F(" "));
long_result = divide0( long_numerator ) ;
Serial.print(long_result,HEX);
Serial.println();
Serial.print(F("ulong uint ulong "));
long_result = unsigned_int_numerator / unsigned_long_denominator ;
Serial.print(long_result,HEX);
Serial.print(F(" "));
long_result = divide0( unsigned_int_numerator ) ;
Serial.print(long_result,HEX);
Serial.println();
Serial.print(F("ulong uint byte "));
long_result = unsigned_int_numerator / byte_denominator ;
Serial.print(long_result,HEX);
Serial.print(F(" "));
long_result = divide0( unsigned_int_numerator ) ;
Serial.print(long_result,HEX);
Serial.println();
Serial.print(F("ulong uint int "));
long_result = unsigned_int_numerator / int_denominator ;
Serial.print(long_result,HEX);
Serial.print(F(" "));
long_result = divide0( unsigned_int_numerator ) ;
Serial.print(long_result,HEX);
Serial.println();
Serial.print(F("ulong uint uint "));
long_result = unsigned_int_numerator / unsigned_int_denominator ;
Serial.print(long_result,HEX);
Serial.print(F(" "));
long_result = divide0( unsigned_int_numerator ) ;
Serial.print(long_result,HEX);
Serial.println();
Serial.print(F("ulong uint long "));
long_result = unsigned_int_numerator / long_denominator ;
Serial.print(long_result,HEX);
Serial.print(F(" "));
long_result = divide0( unsigned_int_numerator ) ;
Serial.print(long_result,HEX);
Serial.println();
Serial.print(F("ulong uint ulong "));
long_result = unsigned_int_numerator / unsigned_long_denominator ;
Serial.print(long_result,HEX);
Serial.print(F(" "));
long_result = divide0( unsigned_int_numerator ) ;
Serial.print(long_result,HEX);
Serial.println();
ulong byte byte FFFFFFFF FF
ulong byte int FFFFFFFF FF
ulong byte uint FFFF FF
ulong byte long FFFFFFFF FF
ulong byte ulong FFFFFFFF FF
ulong int byte FFFFFFFF FFFFFFFF
ulong int int FFFFFFFF FFFFFFFF
ulong int uint FFFF FFFFFFFF
ulong int long FFFFFFFF FFFFFFFF
ulong int ulong FFFFFFFF FFFFFFFF
ulong long byte FFFFFFFF FFFFFFFF
ulong long int FFFFFFFF FFFFFFFF
ulong long uint FFFFFFFF FFFFFFFF
ulong long long FFFFFFFF FFFFFFFF
ulong uint ulong FFFFFFFF FFFF
ulong uint byte FFFF FFFF
ulong uint int FFFF FFFF
ulong uint uint FFFF FFFF
ulong uint long FFFFFFFF FFFF
ulong uint ulong FFFFFFFF FFFF
I was surprised to see that divide by 0 for a long or unsigned long doesn't always result in the same answer, but I think I understand why it's happening, the maths are done before knowing the type of the result.
Normally, I would change the equation to something like:
long_result = (unsigned long)unsigned_byte_numerator / unsigned_int_denominator ;
But I'm hoping to not restrict these macros to specific types (and can't actually figure out how to restrict them anyway).
I guess the worst one is that unsigned int as a denominator has a different result than int as a denominator, so sizeof() isn't the answer.
Can anyone point me in the right direction to either figure out the variable type, or determine how to handle the exceptions based on the limited information available within the macro?