Dividing Without Divide
June 25, 2019
Today’s task comes from a student programmer:
Given a numerator and divisor of unsigned integers, compute the quotient and remainder. You cannot use divide, cannot use mod, and you want to optimize for speed.
After a while, the student programmer looked up the official solution:
def divide_problem(num, div): quotient = 1 while num - (quotient * div) >= div: print(num - (quotient * div), "loop") quotient += 1 remainder = num - (quotient * div) return quotient, remainder
Your task is to comment on the official solution and write a better one. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.
I sure hope this “official solution” was not what was expected for the best possible solution to this! It’s unnecessary long and void of any creativity. Anyway, here is my take on this using Julia 1.0.2:
function divide(n::Int64, d::Int64)
q = floor(Int64, exp(log(n) – log(d)))
r = n – q*d
end
Thanks for the creatively challenging problem.
Good try, but floor is a divide operation.
@Pascal. I had no idea. Thank you for your feedback…
Simple Rust version without multiplication (faster):
Playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=dc817f9b2d6eede71bc8f01565e00707
This recursive Rust version using the left shift operator is much faster than the above when the numerator is a big multiple of the divisor (5 times faster in the benchmark below vs the subtraction-based version above).
Playground https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=e9c9248bfa96af7662e68b01c6195a65
Sorry last post, non-recursive version is simpler and faster:
Playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=71ce4d75d6b16522c3cf8edbbc6b5518
There are at least 2 problems with the “official” solution:
It gives an incorrect answer if div > num. For example, divide_problem(3,5) returns quotient = 1 with remainder = -2.
It runs as O(quotient). E.g., for divide_problem(100,3) the loop runs 33 times.
This recursive Python solution runs as O(log2(quotient)):
Or, as an iterative version:
Here’s a solution in Python.