Avoiding zero divide?

 

I know that the zero divide error occurs when you try to divide something by zero.

I'm not going to start asking people to look through my code for me, but I wondered if there are any good strategies to avoid or locate zero divides? This must be a common problem, but there appears to be no formal standard strategy to help avoid it.

I have three questions about avoiding the error:

1) I have always relied on conditionals to avoid zero errors. Am I right in thinking that placing a conditional before a calculation to make sure that the divisor does not equal zero will avoid the problem? eg.

if ( divisor != 0 )

{ result = dividend/divisor; }

I ran a quick script to check this, and if the conditional is there then zero divide error is avoided, but if the conditional is removed then zero divide error occurs. Can anyone confirm that I am correct in assuming that this is a reliable method of avoiding zero errors?

2) However, the use of the conditional in this way breaks down if there is a divisor *IN* that conditional! eg.

if ( (dividend/divisor) != 0 )

{ result = dividend_two/(dividend/divisor); }

This piece of code would stop a zero divide error occurring in the command, but the error could obviously still occur in the conditional if "divisor == 0". The problem is not avoided by simply placing " && (divisor != 0)" in that conditional.

One way to avoid the error is to place the whole thing in ANOTHER conditional to first check that "divisor != 0" ... but this can start getting very messy if there are lots of divisions going on throughout the code. Is there a more efficient way of approaching this?

3) Is there a better way of searching for "/" signs in the code than just using the search function?

Searching for the "/" brings up matches with all the "//" prefixes in the code. I have those for making comments in virtually every other line of my code, and after a few thousand lines it gets painful. Is there a way to differentiate between "/" as used in divisions and "/" as used elsewhere when searching for zero errors?

 
Is there a way to differentiate between "/" as used in divisions and "/" as used elsewhere when searching for zero errors?

Good coding style recommends that you surround all your operators with spaces

a = b / c;

instead of

a=b/c;

I know this is painful if you are not used to it but consciously forcing yourself do do this for one week will make your muscle-memory remember it eventually.


For avoiding the zero divisions the best way is to do somthing like this:

if (c != 0) {
  a = b / c;
} else {
  print("*** FIXME: c was zero while trying to calculate <whatever>, this is a bug in my program. Find the root cause!");
  a = whatever_makes_sense_now; // either handle it gracefully or stop processing at this point entirely.
}

Then you will get a meaningful error message and can try to investigate *why* it was zero in the first place and detect this condition much earlier (maybe missing history data or something) and do entirely different things to react to it (not even start your calculations but instead try to solve or deal with the root cause)

 
7bit:

Good coding style recommends that you surround all your operators with spaces

a = b / c;

instead of

a=b/c;

I know this is painful if you are not used to it but consciously forcing yourself do do this for one week will make your muscle-memory remember it eventually.

I have started doing this recently . . . also means that the Metaeditor search can be use to search for " / " :-)
 

clerin6:

2) However, the use of the conditional in this way breaks down if there is a divisor *IN* that conditional! eg.

This piece of code would stop a zero divide error occurring in the command, but the error could obviously still occur in the conditional if "divisor == 0". The problem is not avoided by simply placing " && (divisor != 0)" in that conditional.

you place this in front of the division:

if ((divisor != 0) && ((something / divisor) != 0))

because these expressions are evaluated lazily it will stop evaluating the rest of the condition if t finds that the first operand of the && is false, at this point it is proven that the expression can *never* be true anyways, so it does not need to evaluate the rest anymore and will simply skip it.

Edit:

and btw the above can save a few cpu cycles if you do this instead:

if ((divisor != 0) && (something != 0))

because this is totally equivalent, you don't need to divide to find out whether the result of the division will be zero, there is only one possible way this can ever happen.


 

Thanks, I will try to get used to placing spaces either side of the division sign. You're right, it might be a pain but it is better than having to search through the swamp to find those signs later.

I had previously assumed that it would stop evaluating the conditional if there was something like "&& (divisor != 0 )" at the beginning, but I just tried it again as a script and it still came up with a zero error as it did before.

I just ran this in the start() function of a script:

double divisor = 0;
double something = 1;   
   
if ((divisor != 0) && ((something / divisor) != 0))   
{Comment(something / divisor);}

It does not give a comment in the chart, but it does log a new zero divide error in the experts tab.

Is there something I'm missing?

- edit -

Using "if ((divisor != 0) && (something != 0))" does stop the zero divide error from occurring, but I'm assuming that works because it is checking the "something" variable directly, rather than relying on the conditional being skipped after "divisor != 0" ...

 
clerin6:

It does not give a comment in the chart, but it does log a new zero divide error in the experts tab.

Then mql4 is even more broken than I had assumed. Every sane programming language would skip the right part of the && when the left part is evaluated to False. The mql4 docs don't mention anything about this topic and I simply assumed what would be considered normal intuitive behavior as known from any other language (But I have never actually tried to exploit lazy evaluation mql4 myself), it seems I was wrong and it has never worked this way in mql4, I might have confused it with some other programming language.

 
Doh, I was hoping you were right, because I think I may have made the same assumption as you in the past without checking it. I only just checked it today because of this. I'm surprised I hadn't noticed before ...