Skip to content
David Bürgin edited this page Feb 19, 2014 · 5 revisions

Notes on design and implementation choices.

Division and remainder

While there is generally no contention among programming languages as far as the quotient and remainder of positive operands are concerned, they do disagree when it comes to the quotient and remainder of negative operands. Here's a quick overview and comparison with other programming languages.

Div implements truncating division, that is,

  • it is the same as the / operator in Vim script, C, Java, JavaScript, the Python decimal module, Go, and Bash;
  • it is not the same as the / operator in Ruby, Python (//), and Tcl, which implement floored division.

Similarly, Rem

  • is the same as the % operator in Vim script, C, Java, JavaScript, the Python decimal module, Go, Bash, and AWK;
  • it is also the same as remainder in Ruby, rem in Clojure, rem in Haskell, and Rem in Go's big integer library;
  • but it is not the same as % in Python, Ruby, Perl, and Tcl, which implement floored division.

For Div, Rem, and DivRem the Java standard library class java.math.BigInteger is a close model in both name and behaviour: it has divide, remainder, and divideAndRemainder, which produce the same results as the corresponding functions of magnum.vim.

Euclidean division and modulus

The fact that DivRem implements truncating division is simply a design choice. If you need a different type of division you must implement it yourself.

For example, here is an extension of magnum.vim that implements Euclidean division and modulus.

" Returns the pair [quotient, modulus] obtained by dividing x by y using
" Euclidean division.
function! DivMod(x, y) abort
  let [l:q, l:r] = a:x.DivRem(a:y)
  if !l:r.IsNegative()
    return [l:q, l:r]
  elseif a:y.IsPositive()
    return [l:q.Sub(g:magnum#ONE), l:r.Add(a:y)]
  else
    return [l:q.Add(g:magnum#ONE), l:r.Sub(a:y)]
  endif
endfunction

See Daan Leijen, 'Division and modulus for computer scientists'.

Clone this wiki locally