Long multiplication: Difference between revisions

m
Fixed lang tags.
m (Fixed lang tags.)
Line 10:
=={{header|Ada}}==
The following implementation uses representation of a long number by an array of 32-bit elements:
<lang ada>type Long_Number is array (Natural range <>) of Unsigned_32;
<lang ada>
type Long_Number is array (Natural range <>) of Unsigned_32;
 
function "*" (Left, Right : Long_Number) return Long_Number is
Result : Long_Number (0..Left'Length + Right'Length - 1) := (others => 0);
Accum : Unsigned_64;
begin
for I in Left'Range loop
for J in Right'Range loop
Accum := Unsigned_64 (Left (I)) * Unsigned_64 (Right (J));
for K in I + J..Result'Last loop
exit when Accum = 0;
Accum := Accum + Unsigned_64 (Result (K));
Result (K) := Unsigned_32 (Accum and 16#FFFF_FFFF#);
Accum := Accum / 2**32;
end loop;
end loop;
end loop;
end loop;
for Index in reverse Result'Range loop -- Normalization
for Index in ifreverse Result'Range (Index) /=loop 0-- thenNormalization
returnif Result (0..Index); /= 0 then
endreturn ifResult (0..Index);
end loopif;
end loop;
return (0 => 0);
endreturn "*"(0 => 0);
end "*";</lang>
The task requires conversion into decimal base. For this we also need division to short number with a remainder. Here it is:
<lang ada>procedure Div
( Dividend : in out Long_Number;
procedure Div
(Last Dividend : in out Long_NumberNatural;
Last Remainder : in out NaturalUnsigned_32;
Divisor Remainder : out Unsigned_32;
) Divisor : Unsigned_32is
Div : constant Unsigned_64 := Unsigned_64 (Divisor);
) is
Div Accum : constant Unsigned_64 := Unsigned_64 (Divisor)0;
Size : Natural Accum : Unsigned_64 := 0;
begin
Size : Natural := 0;
for Index in reverse ResultDividend'RangeFirst..Last loop -- Normalization
begin
forAccum Index:= inAccum reverse* 2**32 + Unsigned_64 (Dividend'First..Last loop(Index));
Dividend Accum(Index) := Unsigned_32 (Accum */ 2**32 + Unsigned_64 (Dividend (Index)Div);
if Size = 0 and then Dividend (Index) :/= Unsigned_320 (Accum / Div);then
if Size := 0 and then Dividend (Index) /= 0 then;
end Size := Indexif;
Accum := Accum endmod ifDiv;
end Divloop;
Accum := Accum mod Div;
Remainder := Unsigned_32 (Accum);
end loop;
RemainderLast := Unsigned_32 (Accum)Size;
end Div;</lang>
Last := Size;
end Div;
</lang>
With the above the test program:
<lang ada>with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
<lang ada>
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO; use Ada.Text_IO;
with Interfaces; use Interfaces;
Line 87 ⟶ 82:
begin
Put (X);
end Long_Multiplication;</lang>
</lang>
Sample output:
<pre>
Line 100 ⟶ 94:
[[ALGOL 68G]] allows any precision for '''long long int''' to be defined
when the program is run, e.g. 200 digits.
<lang algolalgol68>PRAGMAT precision=200 PRAGMAT
MODE INTEGER = LONG LONG INT;
 
Line 133 ⟶ 127:
{{works with|ALGOL 68G|Any - tested with release mk15-0.8b.fc9.i386}}
<!-- {{does not works with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release 1.8.8d.fc9.i386 - translator throws and assert. I'm not sure why.}} -->
<lang algolalgol68>MODE DIGIT = INT;
MODE INTEGER = FLEX[0]DIGIT; # an arbitary number of digits #
 
Line 226 ⟶ 220:
IF leading zeros = UPB out THEN "0" ELSE sign + out[leading zeros+1:] FI
);</lang>
<lang algolalgol68>################################################################
# Finally Define the required INTEGER multiplication OPerator. #
################################################################
Line 249 ⟶ 243:
NORMALISE ab
);</lang>
<lang algolalgol68># The following standard operators could (potentially) also be defined #
OP - = (INTEGER a)INTEGER: raise integer not implemented error("monadic minus"),
ABS = (INTEGER a)INTEGER: raise integer not implemented error("ABS"),
Anonymous user