5
\$\begingroup\$

You can see it live here: https://flatassembler.github.io/multiplying-strings-aec.html

Function get_length_of_the_first_number() Which Returns Integer32 Is External;
Function get_digit_of_the_first_number_at(Integer32 index) Which Returns Character Is External;
Function get_length_of_the_second_number() Which Returns Integer32 Is External;
Function get_digit_of_the_second_number_at(Integer32 index) Which Returns Character Is External;
Function putc(Character char) Which Returns Nothing Is External;
Function logString(PointerToCharacter string) Which Returns Nothing Is External;

Character matrix[100*100];
Function f(Integer16 i, Integer16 j) Which Returns Integer32 Does
    Return i * 100 + j;
EndFunction

Character result[100];

Function get_length_of_the_result() Which Returns Integer16 Does
    Integer16 i := 0;
    While i < 100 Loop
        If result[i]=0 Then
            Return i;
        EndIf
        i += 1;
    EndWhile
    Return i;
EndFunction

Function prepend_a_character_to_the_result(Character char) Which Returns Nothing Does
    Integer16 i := get_length_of_the_result() + 1;
    While i > 0 Loop
        result[i]:=result[i - 1];
        i -= 1;
    EndWhile
    result[0] := char;
EndFunction

Function multiply() Which Returns Nothing Does
    // Initializing the matrix...
    Integer32 i := 0, j := 0;
    While i < get_length_of_the_second_number() Loop
        j := 0;
        While j < get_length_of_the_first_number() + get_length_of_the_second_number() + 1 Loop
            matrix[f(i,j)] := ' ';
            j += 1;
        EndWhile
        i += 1;
    EndWhile
    logString("The matrix is successfully filled with spaces.");

    //Filling up the matrix...
    Integer32 pointer_to_the_digit_in_the_second_number := 0;
    While pointer_to_the_digit_in_the_second_number < get_length_of_the_second_number() Loop
        Integer16 carry := 0,
            pointer_to_the_matrix_column := get_length_of_the_first_number() +
                pointer_to_the_digit_in_the_second_number + 1;
        Integer16 pointer_to_the_digit_in_the_first_number := get_length_of_the_first_number() - 1;
        While pointer_to_the_digit_in_the_first_number >= 0 Loop
            Integer16 product :=
                (get_digit_of_the_first_number_at(pointer_to_the_digit_in_the_first_number) - '0') *
                (get_digit_of_the_second_number_at(pointer_to_the_digit_in_the_second_number) - '0') +
                carry;
            matrix[f(pointer_to_the_digit_in_the_second_number, pointer_to_the_matrix_column)]
                := mod(product, 10) + '0';
            If product >= 10 Then
                carry := product / 10;
            Else
                carry := 0;
            EndIf
            pointer_to_the_matrix_column -= 1;
            pointer_to_the_digit_in_the_first_number -= 1;
        EndWhile
        If carry Then
            matrix[f(pointer_to_the_digit_in_the_second_number,pointer_to_the_matrix_column)] :=
                mod(carry, 10) + '0';
        EndIf
        If carry >= 10 Then
            pointer_to_the_matrix_column -= 1;
            matrix[f(pointer_to_the_digit_in_the_second_number, pointer_to_the_matrix_column)] := 
                carry / 10 + '0';
        EndIf
        pointer_to_the_digit_in_the_second_number += 1;
    EndWhile
    logString("The matrix is now filled with the products of the first number and the digits of the second.");
    
    //Summing up the matrix...
    result[0]:=0;
    Integer16 carry := 0;
    i := get_length_of_the_first_number() + get_length_of_the_second_number();
    While i >= 0 Loop
        Integer32 sum := carry;
        j := 0;
        While j < get_length_of_the_second_number() Loop
            If not(matrix[f(j, i)] = ' ') Then
                sum += matrix[f(j, i)] - '0';
            EndIf
            j += 1;
        EndWhile
        prepend_a_character_to_the_result(mod(sum, 10) + '0');
        carry := sum / 10;
        i -= 1;
    EndWhile
    If carry Then
        prepend_a_character_to_the_result(carry + '0');
    EndIf
    logString("The matrix is now summed up and the product of the two numbers is calculated.");

    //Replace the trailing zeros with spaces. Now that's a lot easier to do in AEC than in JavaScript...
    i := 0;
    While result[i] = '0' Loop
        result[i] := ' ';
        i += 1;
    EndWhile
    logString("The trailing zeros in the result are now replaced by spaces.");

    //Print the result...
    putc(' ');
    putc(' ');
    i := 0;
    While i < get_length_of_the_first_number() Loop
        putc(get_digit_of_the_first_number_at(i));
        i += 1;
    EndWhile
    putc('*');
    i := 0;
    While i < get_length_of_the_second_number() Loop
        putc(get_digit_of_the_second_number_at(i));
        i += 1;
    EndWhile
    putc('\n');
    
    i := 0;
    While i < get_length_of_the_first_number() + get_length_of_the_second_number() + 1 + 2 Loop
        putc('-');
        i += 1;
    EndWhile
    putc('\n');

    i := 0;
    While i < get_length_of_the_second_number() Loop
        j := 0;
        While j < get_length_of_the_first_number() + get_length_of_the_second_number() + 1 Loop
            putc(matrix[f(i,j)]);
            j += 1;
        EndWhile
        putc('\n');
        i += 1;
    EndWhile
    
    i := 0;
    While i < get_length_of_the_first_number() + get_length_of_the_second_number() + 1 Loop
        putc('-');
        i += 1;
    EndWhile
    putc('\n');

    i := 0;
    While result[i] Loop
        putc(result[i]);
        i += 1;
    EndWhile
    putc('\n');

    logString("The result should be visible on the screen now!");
EndFunction

\$\endgroup\$

1 Answer 1

8
\$\begingroup\$
//Replace the trailing zeros with spaces. Now that's a lot easier to do in AEC than in JavaScript...
i := 0;
While result[i] = '0' Loop
    result[i] := ' ';
    i += 1;
EndWhile

If the result is zero, this doesn't leave a single zero, the entire number is gone. You can compensate for that later too.

If product >= 10 Then
    carry := product / 10;
Else
    carry := 0;
EndIf

carry := product / 10; is enough, you don't need the other case, the carry will be naturally zero anyway.

Character matrix[100*100];

If you add a partial product to the result while forming it, you don't need to store partial products temporarily before adding them. Not having to deal with that matrix could simplify the code in several places.

Regarding prepend_a_character_to_the_result, prepending characters in this way is awkward, I suggest doing something to avoid it. For example:

  • Building the result at the end of the array, printing the result "from the middle" (wherever the leading digit ends up).
  • Building the result from the least significant digit up, printing it in reverse.

If you want to be fancy, you can merge a small chunk of adjacent digits into one, eg take 4 digits to form a number between 0 and 9999 (inclusive range) and do the multiplication in base 10000 (I chose 10000 because the product still fits in a 32-bit integer, and the conversion back to decimal is simple unlike a power-of-two base). Reducing the number of "digits" by a factor of about 4 that way reduces the number of multiplications by a factor of about 16x. A lot more algorithmic trickery is possible but that may not quite fit this question, I'd be happy to add it if you want.

\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.