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
asked Jul 3 at 14:51
\$\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.

answered Jul 3 at 19:02
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.