Runtime of Seemingly Unpredictable Division Algorithm

Click For Summary

Discussion Overview

The discussion revolves around estimating the runtime of a division algorithm implemented using only addition and subtraction. Participants explore the efficiency of the algorithm, its recursive nature, and potential improvements or alternative approaches to runtime estimation.

Discussion Character

  • Exploratory
  • Technical explanation
  • Debate/contested
  • Mathematical reasoning

Main Points Raised

  • One participant describes their initial naive approach of repeated subtraction and subsequent development of a more efficient algorithm, seeking advice on estimating runtime.
  • Another participant suggests that the number of calls to the recursive function can be estimated and multiplied by the time per call to determine runtime, proposing a formula based on the inputs a and b.
  • Concerns are raised about the correspondence between the provided PDF algorithm and the code, with one participant noting that the code does not reflect the power of 2 concept present in the PDF.
  • Participants discuss the implications of using recursive function calls, noting that they may introduce inefficiencies compared to iterative approaches.
  • A suggestion is made to use an inner loop to double the denominator until it exceeds the numerator, which could simplify the runtime calculation.
  • One participant emphasizes the importance of commenting code for clarity, especially in recursive implementations.
  • Another participant proposes a functional programming approach that could potentially streamline the algorithm's execution.

Areas of Agreement / Disagreement

Participants express differing views on the efficiency and structure of the algorithm, with no consensus on the best approach to estimate its runtime. Some propose alternative methods while others defend the current recursive implementation.

Contextual Notes

Participants note the limitations of the current implementation, including the potential inefficiency of recursion and the lack of clarity in the algorithm due to insufficient comments. The discussion also highlights the dependence on specific programming paradigms and the challenges of estimating runtime in recursive algorithms.

matineesuxxx
Messages
77
Reaction score
6
Last week on my computer science assignment I had to write a division algorithm using only addition and subtraction to tackle a problem. My first attempt was the simple and naive repeated subtraction, although I quickly discovered it was not nearly efficient enough for how I needed to use it, So I developed a quicker one. (I have attached a PDF of the algorithm, and the C code for any who are interested in helping)

The problem is that I want to find the runtime, however I cannot predict when the division will reset with a new numerator, thus I have not even the slightest clue as to the worst case scenario.

Can anybody give me some advice on how to estimate the runtime of such algorithms?

Code:
Code:
int div_help(int a, int b, int bconst, int quotient, int acc){
  if(a-b<0){return 0;}
  if(b==a){return quotient+acc;}
  return b+b > a ? div_help(a-b,bconst, bconst,1,acc+quotient):div_help(a,b+b, bconst,quotient+quotient,acc);
}

int div(int a, int b){
  div_help(a,b,b,1,0);
}

[edit] I don't know if there is a way to properly post code here, so the whitespace at the beginning of each line of code doesn't show up.
 

Attachments

Last edited:
Technology news on Phys.org
matineesuxxx said:
[edit] I don't know if there is a way to properly post code here, so the whitespace at the beginning of each line of code doesn't show up.

Enclose the code between [code] and [/code] tags. I did it for you for this thread.
 
jtbell said:
Enclose the code between [code] and [/code] tags. I did it for you for this thread.
Thank you very much.
 
For given inputs a and b you can write an equation for how many calls to div_help it will need to do. Each call requires about the same amount of time, time_one_call, so multiply the number of calls by that time. My guess is that it will take about time_one_call * a / b

A few comments:
1) I don't see any correspondence between the algorithm in the PDF and your code. The PDF is based on powers of 2, and that doesn't appear in your code at all. You are using repeated addition / subtraction by means of recursive calls.
2) Don't hesitate to add comments to your code. You can even put a single statement on several lines and put a comment on each line. When you are using recursion, you should explain what you are doing with comments.
3) Function calls can take a long time compared to simple arithmetic and loops. Your use of recursive function calls just to repeatedly add / subtract will run a lot slower.
4) Recursive calls often requires special care to make sure that a lower level call is not corrupting a variable whose value needs to be retained in a higher level call. That is language dependent.
 
  • Like
Likes   Reactions: Medicol
FactChecker said:
2) Don't hesitate to add comments to your code. You can even put a single statement on several lines and put a comment on each line. When you are using recursion, you should explain what you are doing with comments...

Yes, I should have commented the code.

Code:
// To caclulate a/b.
// PRE: a > 0, b > 0.
// This implementation simlpy returns 0 if b does not divide a.

int div_help(int a, int b, int bconst, int quotient, int acc){

  // a: numerator
  // b: denominator
  // bconst: original denominator (constant)
  // quotient: numerator that is doubled
  // acc: accumulator

  printf("(%d, %d, %d)\n",a,b,acc);
  if(a-b<0){return 0;}
  if(b==a){return quotient+acc;}

  /*b+b is doubling the denominator then checking if its bigger than a, (largest denominator less than or equal to a)*/
  /*a-b is replacing the old numerator with a-b, and keeping constant denominator, or bconst */

  // if b+b > a, then the new numerator becomes a-b, and reset the denominator, increase acc
  // by the correct power of 2 (which is quotient)

  return b+b > a ? div_help(a-b,bconst, bconst,1,acc+quotient):div_help(a,b+b, bconst,quotient+quotient,acc);
  // else keep doubling the denominator and quotient.

FactChecker said:
1) I don't see any correspondence between the algorithm in the PDF and your code. The PDF is based on powers of 2, and that doesn't appear in your code at all. You are using repeated addition / subtraction by means of recursive calls...

This is probably because I had not commented my code, however I assure you they are one in the same. Since I was not allowed to multiply i had to repeatedly add the denominator, b, to itself and same with quotient.

here is the same example from the pdf as presented by the code code:

(a, b, quotient)

(50, 7, 1)
(50, 14, 2)
(50, 28, 4)
(22, 7, 1)
(22, 14, 2)
(8, 7, 1)
(1, 7, 1)

7 + 1/7
 
Last edited:
matineesuxxx said:
Yes, I should have commented the code.
Wow! That is a lot better. If everyone commented like that, programming would be a lot more fun.
 
FactChecker said:
Wow! That is a lot better. If everyone commented like that, programming would be a lot more fun.

Thanks.

About the recursion, the way I derived the algorithm, it just seemed natural to use recursion, and so far in my course we are not permitted to use any imperative programming techniques as of yet.
 
The runtime would be easier to compute with an inner loop where you would double b until you got the largest number of the form b * 2^n that was <=a, and an outer loop where you would subtract the result from the inner loop and then execute the inner loop again with a - b * 2^n instead of a until you got 0. The recursive function rather obscures this.
In a functional programming style you could use 2 functions, 1 function that computes both the largest b * 2^n <= a and 2^n as well, since we have to add it to the result, and an outer function div(a,b) which returns 2^n + div (a - 2^n b, b).
In a C program, the inner function would have to return a struct.

It's simple to see that b=1 will produce the largest number of iterations in the inner loop: 2log(a) = (the number of binary digits of a).

Every step of the outer loop will make a smaller. Since there is a power of two with a/2 <= 2^n <=a, a will get at least twice as small after each step of the outer loop, so a will lose 1 binary digit at least. If a is of a special form, it's possible to show that a will lose exactly 1 binary digit at each step, so the outer loop will take 2log(a_0) iterations as well. Of course the number of iterations of the inner loop depends on the running value of a as well, so you still have a sum to calculate.

 

Similar threads

  • · Replies 22 ·
Replies
22
Views
4K
Replies
12
Views
2K
Replies
9
Views
3K
  • · Replies 25 ·
Replies
25
Views
3K
  • · Replies 17 ·
Replies
17
Views
2K
  • · Replies 31 ·
2
Replies
31
Views
7K
  • · Replies 2 ·
Replies
2
Views
2K
Replies
73
Views
6K
  • · Replies 5 ·
Replies
5
Views
3K
  • · Replies 23 ·
Replies
23
Views
3K