Search code examples
loopsnumbersprocedureadadivision

BASIC: Understanding my own Ada code. Finding numbers that divide an integer without fractions


I'm supposed to code a procedure that finds all integers that evenly divide a number, and I've come up with a solution that works; unfortunately with my non-existent coding knowledge, I don't know why it works.

Here's the basic code:

Get(Number)
A:=1
for X in 1..Number-1 loop
   A:=A+1;
   C:=Number/A;
   if C*A = Number then
      Put(A)
   end if;
end loop;

I've edited out some pure puts for readability, I understand that A increases with 1 each step of the loop, but I don't quite understand what number C retains each loop. I've tried backtracking by printing it, and it goes between the values 2 and 1 for a value of 10 on the "number". Instead of being 1 or 2, I'd see it as being 10/1, 10/2, 10/3, 10/4, 10/5, 10/6 etc, meaning once we reach the if statement we'll just have, lets say, 10/4*A where A is 4 and viola we get 10 even though 10 isn't divisible by 4.

How is C updated, can anyone explain in simple terms?


Solution

  • I assume that the integers to find must be positive. In that case, the type of Number, A, C and X could instead be Positive. If the input is not a positive number, then a CONSTRAINT_ERROR exception will be raised. This is safer: an exception clearly indicates that something went wrong, and it is better than returning an incorrect result.

    Note that the program never tests whether 1 is a valid divisor, even though it is. This is because A is incremented at the beginning of the loop; since its starting value is 1, the first checked value is 2. In any case, it is better to use X, the loop's variable. On your program, it will take values ranging from 1 until Number - 1, both ends included. In addition, X will behave like a constant inside the loop body, which eliminates the risk of accidentally overwriting its value.

    The value assigned to C is the result of dividing Number over A. Given that these variables are integers, the division result will be truncated. For positive numbers, this is equivalent to "rounding down" the result. If Number is evenly divided by A, then the remainder will be zero, so the multiplication will result in the original value. Otherwise, the remainder will be lost, so the value of C * A will be less than the value of A.

    A simpler approach is to directly calculate the remainder of both numbers, and then check whether it is zero. This is the resulting code:

    procedure Main is
       Number : Positive;
    begin
       Get (Number);
       for A in 1 .. Number loop
          if Number rem A = 0 then
             Put (A);
          end if;
       end loop;
    end Main;