1
$\begingroup$

Recently I began learning a couple array based programming languages: Dyalog APL and BQN. And I cam across this peculiar manner in which division by zero is handled in Dyalog APL. Using the in-built method ⎕DIV a user can change the behaviour of $0÷0$. For instance if ⎕DIV=0 then $0÷0$ will return $1$ and if ⎕DIV=1 then $0÷0$ will return $1$. In BQN the returned value is NaN. IF the numerator is other than 0, an error is returned.

My question is, how does this not cause issues for programming in DYALOG APL? I am unclear what advantage this provides; whereas, throwing an error are returning NaN seems rather useful insofar as it signals to the user there is an issue with their code. Moreover, algebraically this is problematic.

$\endgroup$
12
  • $\begingroup$ Do you mean that returning NaN is never an option in Dyalog APL ? $\endgroup$
    – user16034
    Commented Jan 27, 2023 at 18:02
  • $\begingroup$ Unless this is recreational, don't use the APL language. There are better options nowadays (Python Numpy, Matlab, R...) $\endgroup$
    – user16034
    Commented Jan 27, 2023 at 18:05
  • $\begingroup$ @YvesDaoust yes not an option and yes just recreationally, professionally I stick to Julia and Python. $\endgroup$ Commented Jan 27, 2023 at 18:20
  • $\begingroup$ @YvesDaoust, APL of course has an absurd syntax (conceived first as a handwritten notation, then over-suited to now-ancient IBM computer hardware), but it's an absolute goldmine of theory, of concepts, and of terminology. $\endgroup$
    – Steve
    Commented Jan 28, 2023 at 11:46
  • $\begingroup$ @Steve: an absolute goldmine of theory: let me disagree with that. A bunch of operators dealing with matrices, but very little new as regards the theory of languages. Completely unreadable, alien to structured programming, leading to quite inefficient code, limited in scope, requiring a Martian keyboard... I liked it in 1979 but it is now completely outdated. $\endgroup$
    – user16034
    Commented Jan 29, 2023 at 11:11

2 Answers 2

3
$\begingroup$

I might be about to provide an unusual perspective on this, but in my view there is no one convention on division that suits all practical purposes.

I can certainly recall code I've fixed in the past - I forget any exact details - where a division by zero was not considered an error at all, but the result was intended to be zero in the case that the divisor (an integer) was zero.

There was probably no great mathematical integrity to this calculation, but the fix was simply to hard-code a result of zero when the divisor was zero, to avoid provoking an error.

Cobbling together what I can remember of this kind of situation, these sorts of calculations are common when trying to calculate distributional questions, like "how many people will receive what share of a dividend?".

In the case where there are no recipients available, the share is zero (as is the count of recipients). This is practically equivalent to the case where there are potential recipients, but the dividend is zero, so each share is zero - this case would cause no error anyway.

In these kinds of calculations, the programmer does not typically think of the quotient as having a mathematical relationship to the dividend, but of a zero quotient as being a special case which models the case of "no distribution occurs" or "nothing is transferred" in the real world. An absence of recipients (a zero divisor) is just as capable of causing "no distribution" as is an absence of anything to transfer (a zero dividend).

Division is the only standard arithmetical operator where inputting a seemingly non-extreme quantity is capable of producing a crash. I don't even specifically remember what I was taught at school about the result of a division by zero, but I certainly don't recall being told the result is "NaN" or "Error". I suspect something was murmured about "don't do that", but with no guidance on how to systematically handle practical situations which call for division by zero.

This unusual behaviour of computerised division is the cause of error (or of extra programming effort) in simple arithmetic, far more often than it helps identify an error.

Because APL seems to originate in a philosophy of using mathematics for practical data-processing purposes, rather than in trying to express a single coherent system of mathematical tenets, making division by zero a non-error, and being able to determine the default result of such division, seems perfectly sensible.

Also, whilst division by zero = 0 or 1 violates certain standard mathematical properties, it almost certainly acquires new desirable properties which are useful in conjunction with other functions in APL.

$\endgroup$
1
  • $\begingroup$ Okay that's is an example that makes sense to me, thank you. I'll say it discouraged me a bit on APL and I'll probably stick to BQN. Most certainly a bias I have because of my background in mathematics but also would rather avoid ever having to think 'do I need to set 0 divide by 0 to 1 or 0 in this instance' rather than solving a problem in a way that would avoid it. Thank you again for the answer. $\endgroup$ Commented Jan 28, 2023 at 23:30
0
$\begingroup$

how does this not cause issues for programming in DYALOG APL?

Truth to be told, it does cause issues, but maybe not the issues you'd think: The real issue is the introduction of a global variable that governs core language behaviour. If one expects divisions by zero, then it is wise to set a local value for ⎕DIV. However, APLers are largely used to such issues, as multiple settings exist which affect the core language; ⎕IO, ⎕ML, and more.

I am unclear what advantage this provides;

Depending on the exact algorithms in use, either of the two values could be the "correct" one for edge cases. (It should be noted that APLers often expect edge cases to "just work" — more on that below.) For example, if we're computing the percentage of apples in the first bucket:

      buckets ← 3 1 4
      first ← ⊃ buckets
      100 × first ÷ +/buckets   ⍝ +/ is sum
37.5

Now for the edge case where there are no buckets at all (keeping in mind that by default, $0÷0$ gives 1):

      buckets ← ⍬   ⍝ empty list
      first ← ⊃ buckets   ⍝ this gives the fill-value 0
      100 × first ÷ +/buckets
100

Which is correct; "all" the apples are in the first bucket.

Now we want to compute the average number of apples per bucket:

      (+/buckets) ÷ ⍴ buckets   ⍝ ⍴ is length
1

That makes little sense, and arguably 0 would have been a better value:

      ⎕DIV ← 1   ⍝ let 0 ÷ 0 give 0
      (+/buckets) ÷ ⍴ buckets
0

whereas, throwing an error are returning NaN seems rather useful insofar as it signals to the user there is an issue with their code.

APL code will often compute multiple values at once. If such divisions errored when even one of multiple collections hit edge cases, the programmer would have a preprocessing task to filter those out first. Conversely, giving NaNs would force a postprocessing task of cleaning those out. With the current behaviour, the appropriate results can be computed directly.

Moreover, algebraically this is problematic.

But algorithmically sound.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.