Because frequently division by zero indicates a bug. But similarly frequently, I end up crapping out annoying little bits of code like
if (foo == 0):
return 0
else:
return bar / fooBecause frequently division by zero indicates a bug. But similarly frequently, I end up crapping out annoying little bits of code like
if (foo == 0):
return 0
else:
return bar / fooYou say that you frequently have to write your little shim but honestly I don't remember writing code like that in recent memory.
You talk about progress bars, I suppose it makes sense if you somehow try to copy 0 elements for instance, and you end up dividing by zero when computing the progress, like:
pos_percent = (copied_elems * 100) / total_elems
And both copied_elems and total_elems are zero. But in this case wouldn't you want the computation to return 100% instead of zero?It's also a bit odd because it introduces a discontinuity: as the divisor goes towards zero the result of the operation gets greater until it reaches exactly zero and it yields 0. Wouldn't it make more sense to return INT_MAX (for integers) or +inf for floats? If you're writing a game for instance it might work better.
I guess it just goes to show that it probably makes a lot of sense to leave it undefined and let people write their own wrapper if necessary to do what works best for them in their given scenario.
Of course, it's context dependent. As others mention, your code might be full of stuff like X / (divisor || 1).
X / (divisor || 1).
It's invalid code in C, C++ and Java. % cat >division.c <<EOF
#include <stdio.h>
int main(void)
{
printf("1/0 = %d\n", 1 / (0 || 1));
printf("1/2 = %d\n", 1 / (2 || 1));
printf("1.0/0 = %f\n", 1.0 / (0 || 1));
printf("1.0/2 = %f\n", 1.0 / (2 || 1));
}
% gcc -Wall -o divison divison.c
% ./divison
1/0 = 1
1/2 = 1
1.0/0 = 1.000000
1.0/2 = 1.000000
In Python this is not the case: % python3
>>> 1 / (0 or 1)
1
>>> 1. / (0 or 1)
1.0
>>> 1 / (0 or 1)
1
>>> 1. / (2 or 1)
0.5
% python3
>>> 1 / (0 or 1)
1.0
>>> 1 / (2 or 1)
0.5C doesn't have booleans and treat them as integers 0 or 1, it can do the math and will always return 1.
https://en.cppreference.com/w/cpp/language/implicit_conversi... (under "Integral promotion")
And C has a boolean type as of C99.
x / (divisor ?: 1)Also, if loading total elements takes a significant amount of time, shouldnt this loading also be reflected in the progess bar?
Defining x / 0 = 0 gets this behavior for free, while leaving zero as an exception means it has to be caught for every single signal calculation, which is a pain when there are potentially dozens of different signals, all of which are counting different things (and have different divisors). I've actually defined a helper function to do this automatically, which also lets me change the default "null object" easily if I choose a different representation or want to apply some baseline value.
Unless you're using unsigned ints, the discontuity will exist no matter what you do, because of negative divisors.
pub fn checked_div(self, rhs: u8) -> Option<u8>
Checked integer division. Computes self / rhs, returning None if rhs == 0.
You would use this as lhs.checked_div(rhs).unwrap_or(your sane default)
This is dramatically better than always returning zero silently, as doing so is bound to be wrong in certain cases. If you run into a situation where you are afraid your RHS may be 0 but still want to do the right thing, this is what you'd use.
Unfortunately, GCC only lets you enable this globally (within a program): see http://www.gnu.org/software/libc/manual/html_node/FP-Excepti....
A "strict" mode is usually always an afterthought once we have errors & people run it in strict mode and facepalm.
One of the first "utilities" I wrote for PHP was something called "pecl/scream", which turned off all the "unchecked" operations across the whole VM.
And in general, this works out poorly for code quality.
You can always (as in OS with lazy allocation) allocate enough memory to get OOM no matter how safe your language is.
return (foo == 0) ? 0 : bar / foo
or even return bar / max(1, foo)
in the case where foo is integer or tiny foo would overflow your range anywayjust for fun, in kotlin (making use of expressions removes some verbosity):
return where(den) {
0 -> 0
else -> num / den
}
return if (den == 0) { 0 }
else { num / den } return foo && bar / fooIsn't this reason the the point of having a utils library with commonly used pieces of code?
if (foo == 0):
return MAX_FLOAT
else:
return bar / foo
is more sound for the given algorithm than "return 0" (still crappy, but more sound).Then use MAX_FLOAT as an error flag instead of 0, which could have been the result of a legal operation (with bar==0).
Just try INT_MIN/-1, can blow most "foolproof" divide logic away.