A-M baby
This commit is contained in:
parent
764da6cbbb
commit
db842d013d
19005 changed files with 197040 additions and 7 deletions
8
Task/Long-multiplication/0DESCRIPTION
Normal file
8
Task/Long-multiplication/0DESCRIPTION
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
In this task, explicitly implement [[wp:long multiplication|long multiplication]]. This is one possible approach to arbitrary-precision integer algebra.
|
||||
|
||||
[[Category:Arbitrary precision]] [[Category:Arithmetic operations]]
|
||||
|
||||
For output, display the result of 2^64 * 2^64. The decimal representation of 2^64 is:
|
||||
18446744073709551616
|
||||
The output of 2^64 * 2^64 is 2^128, and that is:
|
||||
340282366920938463463374607431768211456
|
||||
2
Task/Long-multiplication/1META.yaml
Normal file
2
Task/Long-multiplication/1META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
note: Arbitrary precision
|
||||
21
Task/Long-multiplication/ALGOL-68/long-multiplication-1.alg
Normal file
21
Task/Long-multiplication/ALGOL-68/long-multiplication-1.alg
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
PRAGMAT precision=200 PRAGMAT
|
||||
MODE INTEGER = LONG LONG INT;
|
||||
|
||||
LONG INT default integer width := 69;
|
||||
INT width = 69+2;
|
||||
|
||||
INT fix w = 1, fix h = 1; # round up #
|
||||
|
||||
LONG LONG INT golden ratio w := ENTIER ((long long sqrt(5)-1) / 2 * LENG LENG 10 ** default integer width + fix w),
|
||||
golden ratio h := ENTIER ((long long sqrt(5)+1) / 2 * LENG LENG 10 ** default integer width + fix h);
|
||||
|
||||
test: (
|
||||
print((
|
||||
"The approximate golden ratios, width: ", whole(golden ratio w,width), new line,
|
||||
" length: ", whole(golden ratio h,width), new line,
|
||||
" product is exactly: ", whole(golden ratio w*golden ratio h,width*2), new line));
|
||||
|
||||
INTEGER two to the power of 64 = LONG 2 ** 64;
|
||||
INTEGER neg two to the power of 64 = -(LONG 2 ** 64);
|
||||
print(("2 ** 64 * -(2 ** 64) = ", whole(two to the power of 64*neg two to the power of 64,width), new line))
|
||||
)
|
||||
93
Task/Long-multiplication/ALGOL-68/long-multiplication-2.alg
Normal file
93
Task/Long-multiplication/ALGOL-68/long-multiplication-2.alg
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
MODE DIGIT = INT;
|
||||
MODE INTEGER = FLEX[0]DIGIT; # an arbitary number of digits #
|
||||
|
||||
# "digits" are stored in digit base ten, but 10000 & 2**n (inc hex) can be used #
|
||||
INT digit base = 1000;
|
||||
|
||||
# if possible, then print the digit with one character #
|
||||
STRING hex digit repr = "0123456789abcdefghijklmnopqrstuvwxyz"[AT 0];
|
||||
INT digit base digit width = ( digit base <= UPB hex digit repr + 1 | 1 | 1 + ENTIER log(digit base-1) );
|
||||
|
||||
INT next digit = -1; # reverse order so digits appear in "normal" order when printed #
|
||||
|
||||
PROC raise value error = ([]STRING args)VOID:
|
||||
( print(("Value Error: ", args, new line)); stop );
|
||||
|
||||
PROC raise not implemented error = ([]STRING args)VOID:
|
||||
( print(("Not implemented Error: ", args, new line)); stop );
|
||||
|
||||
PROC raise integer not implemented error = (STRING message)INTEGER:
|
||||
( raise not implemented error(("INTEGER ", message)); SKIP );
|
||||
|
||||
INT half max int = max int OVER 2;
|
||||
IF digit base > half max int THEN raise value error("INTEGER addition may fail") FI;
|
||||
|
||||
INT sqrt max int = ENTIER sqrt(max int);
|
||||
IF digit base > sqrt max int THEN raise value error("INTEGER multiplication may fail") FI;
|
||||
|
||||
# initialise/cast a INTEGER from a LONG LONG INT #
|
||||
OP INTEGERINIT = (LONG LONG INT number)INTEGER:(
|
||||
[1 + ENTIER (SHORTEN SHORTEN long long log(ABS number) / log(digit base))]DIGIT out;
|
||||
LONG LONG INT carry := number;
|
||||
FOR digit out FROM UPB out BY next digit TO LWB out DO
|
||||
LONG LONG INT prev carry := carry;
|
||||
carry %:= digit base; # avoid MOD as it doesn't under handle -ve numbers #
|
||||
out[digit out] := SHORTEN SHORTEN (prev carry - carry * digit base)
|
||||
OD;
|
||||
out
|
||||
);
|
||||
|
||||
# initialise/cast a INTEGER from an LONG INT #
|
||||
OP INTEGERINIT = (LONG INT number)INTEGER: INTEGERINIT LENG number;
|
||||
|
||||
# initialise/cast a INTEGER from an INT #
|
||||
OP INTEGERINIT = (INT number)INTEGER: INTEGERINIT LENG LENG number;
|
||||
|
||||
# remove leading zero "digits" #
|
||||
OP NORMALISE = ([]DIGIT number)INTEGER: (
|
||||
INT leading zeros := LWB number - 1;
|
||||
FOR digit number FROM LWB number TO UPB number
|
||||
WHILE number[digit number] = 0 DO leading zeros := digit number OD;
|
||||
IF leading zeros = UPB number THEN 0 ELSE number[leading zeros+1:] FI
|
||||
);
|
||||
|
||||
#####################################################################
|
||||
Define a standard representation for the INTEGER mode. Note: this is
|
||||
rather crude because for a large "digit base" the number is represented as
|
||||
blocks of decimals. It works nicely for powers of ten (10,100,1000,...),
|
||||
but for most larger bases (greater then 35) the repr will be a surprise.
|
||||
#####################################################################
|
||||
OP REPR = (DIGIT d)STRING:
|
||||
IF digit base > UPB hex digit repr THEN
|
||||
STRING out := whole(ABS d, -digit base digit width);
|
||||
# Replace spaces with zeros #
|
||||
FOR digit out FROM LWB out TO UPB out DO
|
||||
IF out[digit out] = " " THEN out[digit out] := "0" FI
|
||||
OD;
|
||||
out
|
||||
ELSE # small enough to represent as ASCII (hex) characters #
|
||||
hex digit repr[ABS d]
|
||||
FI;
|
||||
|
||||
OP REPR = (INTEGER number)STRING:(
|
||||
STRING sep = ( digit base digit width > 1 | "," | "" );
|
||||
INT width := digit base digit width + UPB sep;
|
||||
[width * UPB number - UPB sep]CHAR out;
|
||||
INT leading zeros := LWB out - 1;
|
||||
FOR digit TO UPB number DO
|
||||
INT start := digit * width - width + 1;
|
||||
out[start:start+digit base digit width-1] := REPR number[digit];
|
||||
IF digit base digit width /= 1 & digit /= UPB number THEN
|
||||
out[start+digit base digit width] := ","
|
||||
FI
|
||||
OD;
|
||||
|
||||
# eliminate leading zeros #
|
||||
FOR digit out FROM LWB out TO UPB out
|
||||
WHILE out[digit out] = "0" OR out[digit out] = sep
|
||||
DO leading zeros := digit out OD;
|
||||
|
||||
CHAR sign = ( number[1]<0 | "-" | "+" );
|
||||
# finally return the semi-normalised result #
|
||||
IF leading zeros = UPB out THEN "0" ELSE sign + out[leading zeros+1:] FI
|
||||
);
|
||||
23
Task/Long-multiplication/ALGOL-68/long-multiplication-3.alg
Normal file
23
Task/Long-multiplication/ALGOL-68/long-multiplication-3.alg
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
################################################################
|
||||
# Finally Define the required INTEGER multiplication OPerator. #
|
||||
################################################################
|
||||
OP * = (INTEGER a, b)INTEGER:(
|
||||
|
||||
# initialise out to all zeros #
|
||||
[UPB a + UPB b]INT ab; FOR place ab TO UPB ab DO ab[place ab]:=0 OD;
|
||||
|
||||
FOR place a FROM UPB a BY next digit TO LWB a DO
|
||||
DIGIT carry := 0;
|
||||
|
||||
# calculate each digit (whilst removing the carry) #
|
||||
FOR place b FROM UPB b BY next digit TO LWB b DO
|
||||
# n.b. result may be 2 digits #
|
||||
INT result := ab[place a + place b] + a[place a]*b[place b] + carry;
|
||||
carry := result % digit base; # avoid MOD as it doesn't under handle -ve numbers #
|
||||
ab[place a + place b] := result - carry * digit base
|
||||
OD;
|
||||
ab[place a + LWB b + next digit] +:= carry
|
||||
|
||||
OD;
|
||||
NORMALISE ab
|
||||
);
|
||||
30
Task/Long-multiplication/ALGOL-68/long-multiplication-4.alg
Normal file
30
Task/Long-multiplication/ALGOL-68/long-multiplication-4.alg
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# 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"),
|
||||
ODD = (INTEGER a)INTEGER: raise integer not implemented error("ODD"),
|
||||
BIN = (INTEGER a)INTEGER: raise integer not implemented error("BIN");
|
||||
|
||||
OP + = (INTEGER a, b)INTEGER: raise integer not implemented error("addition"),
|
||||
- = (INTEGER a, b)INTEGER: raise integer not implemented error("subtraction"),
|
||||
/ = (INTEGER a, b)REAL: ( VOID(raise integer not implemented error("floating point division")); SKIP),
|
||||
% = (INTEGER a, b)INTEGER: raise integer not implemented error("fixed point division"),
|
||||
%* = (INTEGER a, b)INTEGER: raise integer not implemented error("modulo division"),
|
||||
** = (INTEGER a, b)INTEGER: raise integer not implemented error("to the power of");
|
||||
|
||||
LONG INT default integer width := long long int width - 2;
|
||||
|
||||
INT fix w = -1177584, fix h = -3915074; # floating point error, probably GMP/hardware specific #
|
||||
|
||||
INTEGER golden ratio w := INTEGERINIT ENTIER ((long long sqrt(5)-1) / 2 * LENG LENG 10 ** default integer width + fix w),
|
||||
golden ratio h := INTEGERINIT ENTIER ((long long sqrt(5)+1) / 2 * LENG LENG 10 ** default integer width + fix h);
|
||||
|
||||
test: (
|
||||
print((
|
||||
"The approximate golden ratios, width: ", REPR golden ratio w, new line,
|
||||
" length: ", REPR golden ratio h, new line,
|
||||
" product is exactly: ", REPR (golden ratio w * golden ratio h), new line));
|
||||
|
||||
INTEGER two to the power of 64 = INTEGERINIT(LONG 2 ** 64);
|
||||
INTEGER neg two to the power of 64 = INTEGERINIT(-(LONG 2 ** 64));
|
||||
print(("2 ** 64 * -(2 ** 64) = ", REPR (two to the power of 64 * neg two to the power of 64), new line))
|
||||
)
|
||||
88
Task/Long-multiplication/AWK/long-multiplication.awk
Normal file
88
Task/Long-multiplication/AWK/long-multiplication.awk
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
BEGIN {
|
||||
DEBUG = 0
|
||||
n = 2^64
|
||||
nn = sprintf("%.0f", n)
|
||||
printf "2^64 * 2^64 = %.0f\n", multiply(nn, nn)
|
||||
printf "2^64 * 2^64 = %.0f\n", n*n
|
||||
exit
|
||||
}
|
||||
|
||||
function multiply(x, y, len_x,len_y,ax,ay,j,m,c,i,k,d,v,res,mul,result) {
|
||||
len_x = split_reverse(x, ax)
|
||||
len_y = split_reverse(y, ay)
|
||||
print_array(ax)
|
||||
print_array(ay)
|
||||
for (j=1; j<=len_y; j++) {
|
||||
m = ay[j]
|
||||
c = 0
|
||||
i = j - 1
|
||||
for (k=1; k<=len_x; k++) {
|
||||
d = ax[k]
|
||||
i++
|
||||
v = res[i]
|
||||
if (v == "") {
|
||||
append_array(res, 0)
|
||||
v = 0
|
||||
}
|
||||
mul = v + c + d*m
|
||||
c = int(mul / 10)
|
||||
v = mul % 10
|
||||
res[i] = v
|
||||
}
|
||||
append_array(res, c)
|
||||
}
|
||||
print_array(res)
|
||||
result = reverse_join(res)
|
||||
sub(/^0+/, "", result)
|
||||
return result
|
||||
}
|
||||
|
||||
function split_reverse(x, a, a_x) {
|
||||
split(x, a_x, "")
|
||||
return reverse_array(a_x, a)
|
||||
}
|
||||
|
||||
function reverse_array(a,b, len,i) {
|
||||
len = length_array(a)
|
||||
for (i in a) {
|
||||
b[1+len-i] = a[i]
|
||||
}
|
||||
return len
|
||||
}
|
||||
|
||||
function length_array(a, len,i) {
|
||||
len = 0
|
||||
for (i in a) len++
|
||||
return len
|
||||
}
|
||||
|
||||
function append_array(a, value, len) {
|
||||
len = length_array(a)
|
||||
a[++len] = value
|
||||
}
|
||||
|
||||
function reverse_join(a, len,str,i) {
|
||||
len = length_array(a)
|
||||
str = ""
|
||||
for (i=len; i>=1; i--) {
|
||||
str = str a[i]
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
function print_array(a, len,i) {
|
||||
if (DEBUG) {
|
||||
len = length_array(a)
|
||||
print "length=" len
|
||||
for (i=1; i<=len; i++) {
|
||||
printf("%s ", i%10)
|
||||
}
|
||||
print ""
|
||||
for (i=1; i<=len; i++) {
|
||||
#print i " " a[i]
|
||||
printf("%s ", a[i])
|
||||
}
|
||||
print ""
|
||||
print "===="
|
||||
}
|
||||
}
|
||||
34
Task/Long-multiplication/Ada/long-multiplication-1.ada
Normal file
34
Task/Long-multiplication/Ada/long-multiplication-1.ada
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
package Long_Multiplication is
|
||||
type Number (<>) is private;
|
||||
|
||||
Zero : constant Number;
|
||||
One : constant Number;
|
||||
|
||||
function Value (Item : in String) return Number;
|
||||
function Image (Item : in Number) return String;
|
||||
|
||||
overriding
|
||||
function "=" (Left, Right : in Number) return Boolean;
|
||||
|
||||
function "+" (Left, Right : in Number) return Number;
|
||||
function "*" (Left, Right : in Number) return Number;
|
||||
|
||||
function Trim (Item : in Number) return Number;
|
||||
private
|
||||
Bits : constant := 16;
|
||||
Base : constant := 2 ** Bits;
|
||||
|
||||
type Accumulated_Value is range 0 .. (Base - 1) * Base;
|
||||
subtype Digit is Accumulated_Value range 0 .. Base - 1;
|
||||
|
||||
type Number is array (Natural range <>) of Digit;
|
||||
for Number'Component_Size use Bits; -- or pragma Pack (Number);
|
||||
|
||||
Zero : constant Number := (1 .. 0 => 0);
|
||||
One : constant Number := (0 => 1);
|
||||
|
||||
procedure Divide (Dividend : in Number;
|
||||
Divisor : in Digit;
|
||||
Result : out Number;
|
||||
Remainder : out Digit);
|
||||
end Long_Multiplication;
|
||||
145
Task/Long-multiplication/Ada/long-multiplication-2.ada
Normal file
145
Task/Long-multiplication/Ada/long-multiplication-2.ada
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
package body Long_Multiplication is
|
||||
function Value (Item : in String) return Number is
|
||||
subtype Base_Ten_Digit is Digit range 0 .. 9;
|
||||
Ten : constant Number := (0 => 10);
|
||||
begin
|
||||
case Item'Length is
|
||||
when 0 =>
|
||||
raise Constraint_Error;
|
||||
when 1 =>
|
||||
return (0 => Base_Ten_Digit'Value (Item));
|
||||
when others =>
|
||||
return (0 => Base_Ten_Digit'Value (Item (Item'Last .. Item'Last)))
|
||||
+ Ten * Value (Item (Item'First .. Item'Last - 1));
|
||||
end case;
|
||||
end Value;
|
||||
|
||||
function Image (Item : in Number) return String is
|
||||
Base_Ten : constant array (Digit range 0 .. 9) of String (1 .. 1) :=
|
||||
("0", "1", "2", "3", "4", "5", "6", "7", "8", "9");
|
||||
Result : Number (0 .. Item'Last);
|
||||
Remainder : Digit;
|
||||
begin
|
||||
if Item = Zero then
|
||||
return "0";
|
||||
else
|
||||
Divide (Dividend => Item,
|
||||
Divisor => 10,
|
||||
Result => Result,
|
||||
Remainder => Remainder);
|
||||
|
||||
if Result = Zero then
|
||||
return Base_Ten (Remainder);
|
||||
else
|
||||
return Image (Trim (Result)) & Base_Ten (Remainder);
|
||||
end if;
|
||||
end if;
|
||||
end Image;
|
||||
|
||||
overriding
|
||||
function "=" (Left, Right : in Number) return Boolean is
|
||||
begin
|
||||
for Position in Integer'Min (Left'First, Right'First) ..
|
||||
Integer'Max (Left'Last, Right'Last) loop
|
||||
if Position in Left'Range and Position in Right'Range then
|
||||
if Left (Position) /= Right (Position) then
|
||||
return False;
|
||||
end if;
|
||||
elsif Position in Left'Range then
|
||||
if Left (Position) /= 0 then
|
||||
return False;
|
||||
end if;
|
||||
elsif Position in Right'Range then
|
||||
if Right (Position) /= 0 then
|
||||
return False;
|
||||
end if;
|
||||
else
|
||||
raise Program_Error;
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
return True;
|
||||
end "=";
|
||||
|
||||
function "+" (Left, Right : in Number) return Number is
|
||||
Result : Number (Integer'Min (Left'First, Right'First) ..
|
||||
Integer'Max (Left'Last , Right'Last) + 1);
|
||||
Accumulator : Accumulated_Value := 0;
|
||||
Used : Integer := Integer'First;
|
||||
begin
|
||||
for Position in Result'Range loop
|
||||
if Position in Left'Range then
|
||||
Accumulator := Accumulator + Left (Position);
|
||||
end if;
|
||||
|
||||
if Position in Right'Range then
|
||||
Accumulator := Accumulator + Right (Position);
|
||||
end if;
|
||||
|
||||
Result (Position) := Accumulator mod Base;
|
||||
Accumulator := Accumulator / Base;
|
||||
|
||||
if Result (Position) /= 0 then
|
||||
Used := Position;
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
if Accumulator = 0 then
|
||||
return Result (Result'First .. Used);
|
||||
else
|
||||
raise Constraint_Error;
|
||||
end if;
|
||||
end "+";
|
||||
|
||||
function "*" (Left, Right : in Number) return Number is
|
||||
Accumulator : Accumulated_Value;
|
||||
Result : Number (Left'First + Right'First ..
|
||||
Left'Last + Right'Last + 1) := (others => 0);
|
||||
Used : Integer := Integer'First;
|
||||
begin
|
||||
for L in Left'Range loop
|
||||
for R in Right'Range loop
|
||||
Accumulator := Left (L) * Right (R);
|
||||
|
||||
for Position in L + R .. Result'Last loop
|
||||
exit when Accumulator = 0;
|
||||
|
||||
Accumulator := Accumulator + Result (Position);
|
||||
Result (Position) := Accumulator mod Base;
|
||||
Accumulator := Accumulator / Base;
|
||||
Used := Position;
|
||||
end loop;
|
||||
end loop;
|
||||
end loop;
|
||||
|
||||
return Result (Result'First .. Used);
|
||||
end "*";
|
||||
|
||||
procedure Divide (Dividend : in Number;
|
||||
Divisor : in Digit;
|
||||
Result : out Number;
|
||||
Remainder : out Digit) is
|
||||
Accumulator : Accumulated_Value := 0;
|
||||
begin
|
||||
Result := (others => 0);
|
||||
|
||||
for Position in reverse Dividend'Range loop
|
||||
Accumulator := Accumulator * Base + Dividend (Position);
|
||||
Result (Position) := Accumulator / Divisor;
|
||||
Accumulator := Accumulator mod Divisor;
|
||||
end loop;
|
||||
|
||||
Remainder := Accumulator;
|
||||
end Divide;
|
||||
|
||||
function Trim (Item : in Number) return Number is
|
||||
begin
|
||||
for Position in reverse Item'Range loop
|
||||
if Item (Position) /= 0 then
|
||||
return Item (Item'First .. Position);
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
return Zero;
|
||||
end Trim;
|
||||
end Long_Multiplication;
|
||||
11
Task/Long-multiplication/Ada/long-multiplication-3.ada
Normal file
11
Task/Long-multiplication/Ada/long-multiplication-3.ada
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
with Ada.Text_IO;
|
||||
with Long_Multiplication;
|
||||
|
||||
procedure Test_Long_Multiplication is
|
||||
use Ada.Text_IO, Long_Multiplication;
|
||||
|
||||
N : Number := Value ("18446744073709551616");
|
||||
M : Number := N * N;
|
||||
begin
|
||||
Put_Line (Image (N) & " * " & Image (N) & " = " & Image (M));
|
||||
end Test_Long_Multiplication;
|
||||
24
Task/Long-multiplication/Ada/long-multiplication-4.ada
Normal file
24
Task/Long-multiplication/Ada/long-multiplication-4.ada
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
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;
|
||||
for Index in reverse Result'Range loop -- Normalization
|
||||
if Result (Index) /= 0 then
|
||||
return Result (0..Index);
|
||||
end if;
|
||||
end loop;
|
||||
return (0 => 0);
|
||||
end "*";
|
||||
21
Task/Long-multiplication/Ada/long-multiplication-5.ada
Normal file
21
Task/Long-multiplication/Ada/long-multiplication-5.ada
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
procedure Div
|
||||
( Dividend : in out Long_Number;
|
||||
Last : in out Natural;
|
||||
Remainder : out Unsigned_32;
|
||||
Divisor : Unsigned_32
|
||||
) is
|
||||
Div : constant Unsigned_64 := Unsigned_64 (Divisor);
|
||||
Accum : Unsigned_64 := 0;
|
||||
Size : Natural := 0;
|
||||
begin
|
||||
for Index in reverse Dividend'First..Last loop
|
||||
Accum := Accum * 2**32 + Unsigned_64 (Dividend (Index));
|
||||
Dividend (Index) := Unsigned_32 (Accum / Div);
|
||||
if Size = 0 and then Dividend (Index) /= 0 then
|
||||
Size := Index;
|
||||
end if;
|
||||
Accum := Accum mod Div;
|
||||
end loop;
|
||||
Remainder := Unsigned_32 (Accum);
|
||||
Last := Size;
|
||||
end Div;
|
||||
26
Task/Long-multiplication/Ada/long-multiplication-6.ada
Normal file
26
Task/Long-multiplication/Ada/long-multiplication-6.ada
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
|
||||
with Ada.Text_IO; use Ada.Text_IO;
|
||||
with Interfaces; use Interfaces;
|
||||
|
||||
procedure Long_Multiplication is
|
||||
-- Insert definitions above here
|
||||
procedure Put (Value : Long_Number) is
|
||||
X : Long_Number := Value;
|
||||
Last : Natural := X'Last;
|
||||
Digit : Unsigned_32;
|
||||
Result : Unbounded_String;
|
||||
begin
|
||||
loop
|
||||
Div (X, Last, Digit, 10);
|
||||
Append (Result, Character'Val (Digit + Character'Pos ('0')));
|
||||
exit when Last = 0 and then X (0) = 0;
|
||||
end loop;
|
||||
for Index in reverse 1..Length (Result) loop
|
||||
Put (Element (Result, Index));
|
||||
end loop;
|
||||
end Put;
|
||||
|
||||
X : Long_Number := (0 => 0, 1 => 0, 2 => 1) * (0 => 0, 1 => 0, 2 => 1);
|
||||
begin
|
||||
Put (X);
|
||||
end Long_Multiplication;
|
||||
19
Task/Long-multiplication/AutoHotkey/long-multiplication.ahk
Normal file
19
Task/Long-multiplication/AutoHotkey/long-multiplication.ahk
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
MsgBox % x := mul(256,256)
|
||||
MsgBox % x := mul(x,x)
|
||||
MsgBox % x := mul(x,x) ; 18446744073709551616
|
||||
MsgBox % x := mul(x,x) ; 340282366920938463463374607431768211456
|
||||
|
||||
mul(b,c) { ; <- b*c
|
||||
VarSetCapacity(a, n:=StrLen(b)+StrLen(c), 48), NumPut(0,a,n,"char")
|
||||
Loop % StrLen(c) {
|
||||
i := StrLen(c)+1-A_Index, cy := 0
|
||||
Loop % StrLen(b) {
|
||||
j := StrLen(b)+1-A_Index,
|
||||
t := SubStr(a,i+j,1) + SubStr(b,j,1) * SubStr(c,i,1) + cy
|
||||
cy := t // 10
|
||||
NumPut(mod(t,10)+48,a,i+j-1,"char")
|
||||
}
|
||||
NumPut(cy+48,a,i+j-2,"char")
|
||||
}
|
||||
Return cy ? a : SubStr(a,2)
|
||||
}
|
||||
147
Task/Long-multiplication/BASIC/long-multiplication-1.bas
Normal file
147
Task/Long-multiplication/BASIC/long-multiplication-1.bas
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
'PROGRAM : BIG MULTIPLICATION VER #1
|
||||
'LRCVS 01.01.2010
|
||||
'THIS PROGRAM SIMPLY MAKES A MULTIPLICATION
|
||||
'WITH ALL THE PARTIAL PRODUCTS.
|
||||
'............................................................
|
||||
|
||||
DECLARE SUB A.INICIO (A$, B$)
|
||||
DECLARE SUB B.STORE (CAD$, N$)
|
||||
DECLARE SUB C.PIZARRA ()
|
||||
DECLARE SUB D.ENCABEZADOS (A$, B$)
|
||||
DECLARE SUB E.MULTIPLICACION (A$, B$)
|
||||
DECLARE SUB G.SUMA ()
|
||||
DECLARE FUNCTION F.INVCAD$ (CAD$)
|
||||
|
||||
RANDOMIZE TIMER
|
||||
CALL A.INICIO(A$, B$)
|
||||
CALL B.STORE(A$, "A")
|
||||
CALL B.STORE(B$, "B")
|
||||
CALL C.PIZARRA
|
||||
CALL D.ENCABEZADOS(A$, B$)
|
||||
CALL E.MULTIPLICACION(A$, B$)
|
||||
CALL G.SUMA
|
||||
|
||||
SUB A.INICIO (A$, B$)
|
||||
CLS
|
||||
'Note: Number of digits > 1000
|
||||
INPUT "NUMBER OF DIGITS "; S
|
||||
CLS
|
||||
A$ = ""
|
||||
B$ = ""
|
||||
FOR N = 1 TO S
|
||||
A$ = A$ + LTRIM$(STR$(INT(RND * 9)))
|
||||
NEXT N
|
||||
FOR N = 1 TO S
|
||||
B$ = B$ + LTRIM$(STR$(INT(RND * 9)))
|
||||
NEXT N
|
||||
END SUB
|
||||
|
||||
SUB B.STORE (CAD$, N$)
|
||||
OPEN "O", #1, N$
|
||||
FOR M = LEN(CAD$) TO 1 STEP -1
|
||||
WRITE #1, MID$(CAD$, M, 1)
|
||||
NEXT M
|
||||
CLOSE (1)
|
||||
END SUB
|
||||
|
||||
SUB C.PIZARRA
|
||||
OPEN "A", #3, "R"
|
||||
WRITE #3, ""
|
||||
CLOSE (3)
|
||||
KILL "R"
|
||||
END SUB
|
||||
|
||||
SUB D.ENCABEZADOS (A$, B$)
|
||||
LT = LEN(A$) + LEN(B$) + 1
|
||||
L$ = STRING$(LT, " ")
|
||||
OPEN "A", #3, "R"
|
||||
MID$(L$, LT - LEN(A$) + 1) = A$
|
||||
WRITE #3, L$
|
||||
CLOSE (3)
|
||||
L$ = STRING$(LT, " ")
|
||||
OPEN "A", #3, "R"
|
||||
MID$(L$, LT - LEN(B$) - 1) = "X " + B$
|
||||
WRITE #3, L$
|
||||
CLOSE (3)
|
||||
END SUB
|
||||
|
||||
SUB E.MULTIPLICACION (A$, B$)
|
||||
LT = LEN(A$) + LEN(B$) + 1
|
||||
L$ = STRING$(LT, " ")
|
||||
C$ = ""
|
||||
D$ = ""
|
||||
E$ = ""
|
||||
CT1 = 1
|
||||
ACUM = 0
|
||||
OPEN "I", #2, "B"
|
||||
WHILE EOF(2) <> -1
|
||||
INPUT #2, B$
|
||||
OPEN "I", #1, "A"
|
||||
WHILE EOF(1) <> -1
|
||||
INPUT #1, A$
|
||||
RP = (VAL(A$) * VAL(B$)) + ACUM
|
||||
C$ = LTRIM$(STR$(RP))
|
||||
IF EOF(1) <> -1 THEN D$ = D$ + RIGHT$(C$, 1)
|
||||
IF EOF(1) = -1 THEN D$ = D$ + F.INVCAD$(C$)
|
||||
E$ = LEFT$(C$, LEN(C$) - 1)
|
||||
ACUM = VAL(E$)
|
||||
WEND
|
||||
CLOSE (1)
|
||||
MID$(L$, LT - CT1 - LEN(D$) + 2) = F.INVCAD$(D$)
|
||||
OPEN "A", #3, "R"
|
||||
WRITE #3, L$
|
||||
CLOSE (3)
|
||||
L$ = STRING$(LT, " ")
|
||||
ACUM = 0
|
||||
C$ = ""
|
||||
D$ = ""
|
||||
E$ = ""
|
||||
CT1 = CT1 + 1
|
||||
WEND
|
||||
CLOSE (2)
|
||||
END SUB
|
||||
|
||||
FUNCTION F.INVCAD$ (CAD$)
|
||||
LCAD = LEN(CAD$)
|
||||
CADTEM$ = ""
|
||||
FOR CAD = LCAD TO 1 STEP -1
|
||||
CADTEM$ = CADTEM$ + MID$(CAD$, CAD, 1)
|
||||
NEXT CAD
|
||||
F.INVCAD$ = CADTEM$
|
||||
END FUNCTION
|
||||
|
||||
SUB G.SUMA
|
||||
CF = 0
|
||||
OPEN "I", #3, "R"
|
||||
WHILE EOF(3) <> -1
|
||||
INPUT #3, R$
|
||||
CF = CF + 1
|
||||
AN = LEN(R$)
|
||||
WEND
|
||||
CF = CF - 2
|
||||
CLOSE (3)
|
||||
W$ = ""
|
||||
ST = 0
|
||||
ACUS = 0
|
||||
FOR P = 1 TO AN
|
||||
K = 0
|
||||
OPEN "I", #3, "R"
|
||||
WHILE EOF(3) <> -1
|
||||
INPUT #3, R$
|
||||
K = K + 1
|
||||
IF K > 2 THEN ST = ST + VAL(MID$(R$, AN - P + 1, 1))
|
||||
IF K > 2 THEN M$ = LTRIM$(STR$(ST + ACUS))
|
||||
WEND
|
||||
'COLOR 10: LOCATE CF + 3, AN - P + 1: PRINT RIGHT$(M$, 1); : COLOR 7
|
||||
W$ = W$ + RIGHT$(M$, 1)
|
||||
ACUS = VAL(LEFT$(M$, LEN(M$) - 1))
|
||||
CLOSE (3)
|
||||
ST = 0
|
||||
NEXT P
|
||||
|
||||
OPEN "A", #3, "R"
|
||||
WRITE #3, " " + RIGHT$(F.INVCAD(W$), AN - 1)
|
||||
CLOSE (3)
|
||||
CLS
|
||||
PRINT "THE SOLUTION IN THE FILE: R"
|
||||
END SUB
|
||||
107
Task/Long-multiplication/BASIC/long-multiplication-2.bas
Normal file
107
Task/Long-multiplication/BASIC/long-multiplication-2.bas
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
'PROGRAM: BIG MULTIPLICATION VER # 2
|
||||
'LRCVS 01/01/2010
|
||||
'THIS PROGRAM SIMPLY MAKES A BIG MULTIPLICATION
|
||||
'WITHOUT THE PARTIAL PRODUCTS.
|
||||
'HERE SEE ONLY THE SOLUTION.
|
||||
'...............................................................
|
||||
CLS
|
||||
PRINT "WAIT"
|
||||
|
||||
NA = 2000 'NUMBER OF ELEMENTS OF THE MULTIPLY.
|
||||
NB = 2000 'NUMBER OF ELEMENTS OF THE MULTIPLIER.
|
||||
'Solution = 4000 Exacts digits
|
||||
|
||||
'......................................................
|
||||
OPEN "X" + ".MLT" FOR BINARY AS #1
|
||||
CLOSE (1)
|
||||
KILL "*.MLT"
|
||||
'.....................................................
|
||||
'CREATING THE MULTIPLY >>> A
|
||||
'CREATING THE MULTIPLIER >>> B
|
||||
FOR N = 1 TO 2
|
||||
IF N = 1 THEN F$ = "A" + ".MLT": NN = NA
|
||||
IF N = 2 THEN F$ = "B" + ".MLT": NN = NB
|
||||
OPEN F$ FOR BINARY AS #1
|
||||
FOR N2 = 1 TO NN
|
||||
RANDOMIZE TIMER
|
||||
X$ = LTRIM$(STR$(INT(RND * 10)))
|
||||
SEEK #1, N2: PUT #1, N2, X$
|
||||
NEXT N2
|
||||
SEEK #1, N2
|
||||
CLOSE (1)
|
||||
NEXT N
|
||||
'.....................................................
|
||||
OPEN "A" + ".MLT" FOR BINARY AS #1
|
||||
FOR K = 0 TO 9
|
||||
NUM$ = "": Z$ = "": ACU = 0: GG = NA
|
||||
C$ = LTRIM$(STR$(K))
|
||||
OPEN C$ + ".MLT" FOR BINARY AS #2
|
||||
'OPEN "A" + ".MLT" FOR BINARY AS #1
|
||||
FOR N = 1 TO NA
|
||||
SEEK #1, GG: GET #1, GG, X$
|
||||
NUM$ = X$
|
||||
Z$ = LTRIM$(STR$(ACU + (VAL(X$) * VAL(C$))))
|
||||
L = LEN(Z$)
|
||||
ACU = 0
|
||||
IF L = 1 THEN NUM$ = Z$: PUT #2, N, NUM$
|
||||
IF L > 1 THEN ACU = VAL(LEFT$(Z$, LEN(Z$) - 1)): NUM$ = RIGHT$(Z$, 1): PUT #2, N, NUM$
|
||||
SEEK #2, N: PUT #2, N, NUM$
|
||||
GG = GG - 1
|
||||
NEXT N
|
||||
IF L > 1 THEN ACU = VAL(LEFT$(Z$, LEN(Z$) - 1)): NUM$ = LTRIM$(STR$(ACU)): XX$ = XX$ + NUM$: PUT #2, N, NUM$
|
||||
'CLOSE (1)
|
||||
CLOSE (2)
|
||||
NEXT K
|
||||
CLOSE (1)
|
||||
'......................................................
|
||||
ACU = 0
|
||||
LT5 = 1
|
||||
LT6 = LT5
|
||||
OPEN "B" + ".MLT" FOR BINARY AS #1
|
||||
OPEN "D" + ".MLT" FOR BINARY AS #3
|
||||
FOR JB = NB TO 1 STEP -1
|
||||
SEEK #1, JB
|
||||
GET #1, JB, X$
|
||||
|
||||
OPEN X$ + ".MLT" FOR BINARY AS #2: LF = LOF(2): CLOSE (2)
|
||||
|
||||
OPEN X$ + ".MLT" FOR BINARY AS #2
|
||||
FOR KB = 1 TO LF
|
||||
SEEK #2, KB
|
||||
GET #2, , NUM$
|
||||
SEEK #3, LT5
|
||||
GET #3, LT5, PR$
|
||||
T$ = ""
|
||||
T$ = LTRIM$(STR$(ACU + VAL(NUM$) + VAL(PR$)))
|
||||
PR$ = RIGHT$(T$, 1)
|
||||
ACU = 0
|
||||
IF LEN(T$) > 1 THEN ACU = VAL(LEFT$(T$, LEN(T$) - 1))
|
||||
SEEK #3, LT5: PUT #3, LT5, PR$
|
||||
LT5 = LT5 + 1
|
||||
NEXT KB
|
||||
IF ACU <> 0 THEN PR$ = LTRIM$(STR$(ACU)): PUT #3, LT5, PR$
|
||||
CLOSE (2)
|
||||
LT6 = LT6 + 1
|
||||
LT5 = LT6
|
||||
ACU = 0
|
||||
NEXT JB
|
||||
CLOSE (3)
|
||||
CLOSE (1)
|
||||
OPEN "D" + ".MLT" FOR BINARY AS #3: LD = LOF(3): CLOSE (3)
|
||||
ER = 1
|
||||
OPEN "D" + ".MLT" FOR BINARY AS #3
|
||||
OPEN "R" + ".MLT" FOR BINARY AS #4
|
||||
FOR N = LD TO 1 STEP -1
|
||||
SEEK #3, N: GET #3, N, PR$
|
||||
SEEK #4, ER: PUT #4, ER, PR$
|
||||
ER = ER + 1
|
||||
NEXT N
|
||||
CLOSE (4)
|
||||
CLOSE (3)
|
||||
KILL "D.MLT"
|
||||
FOR N = 0 TO 9
|
||||
C$ = LTRIM$(STR$(N))
|
||||
KILL C$ + ".MLT"
|
||||
NEXT N
|
||||
PRINT "END"
|
||||
PRINT "THE SOLUTION IN THE FILE: R.MLT"
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
INSTALL @lib$+"BB4WMAPMLIB"
|
||||
MAPM_DllPath$ = @lib$+"BB4WMAPM.DLL"
|
||||
PROCMAPM_Init
|
||||
|
||||
twoto64$ = "18446744073709551616"
|
||||
PRINT "2^64 * 2^64 = " ; FNMAPM_Multiply(twoto64$, twoto64$)
|
||||
28
Task/Long-multiplication/BBC-BASIC/long-multiplication-2.bbc
Normal file
28
Task/Long-multiplication/BBC-BASIC/long-multiplication-2.bbc
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
twoto64$ = "18446744073709551616"
|
||||
PRINT "2^64 * 2^64 = " ; FNlongmult(twoto64$, twoto64$)
|
||||
END
|
||||
|
||||
DEF FNlongmult(num1$, num2$)
|
||||
LOCAL C%, I%, J%, S%, num1&(), num2&(), num3&()
|
||||
S% = LEN(num1$)+LEN(num2$)
|
||||
DIM num1&(S%), num2&(S%), num3&(S%)
|
||||
IF LEN(num1$) > LEN(num2$) SWAP num1$,num2$
|
||||
$$^num1&(1) = num1$
|
||||
num1&() AND= 15
|
||||
FOR I% = LEN(num1$) TO 1 STEP -1
|
||||
$$^num2&(I%) = num2$
|
||||
num2&() AND= 15
|
||||
num3&() += num2&() * num1&(I%)
|
||||
IF I% MOD 3 = 1 THEN
|
||||
C% = 0
|
||||
FOR J% = S%-1 TO I%-1 STEP -1
|
||||
C% += num3&(J%)
|
||||
num3&(J%) = C% MOD 10
|
||||
C% DIV= 10
|
||||
NEXT
|
||||
ENDIF
|
||||
NEXT I%
|
||||
num3&() += &30
|
||||
num3&(S%) = 0
|
||||
IF num3&(0) = &30 THEN = $$^num3&(1)
|
||||
= $$^num3&(0)
|
||||
11
Task/Long-multiplication/C++/long-multiplication.cpp
Normal file
11
Task/Long-multiplication/C++/long-multiplication.cpp
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#include <cln/integer.h>//for mathematical operations on arbitrarily long integers
|
||||
#include <cln/integer_io.h>//for input/output of long integers
|
||||
#include <iostream>
|
||||
|
||||
int main( ) {
|
||||
cln::cl_I base = 2 , exponent = 64 ;//cln is a namespace
|
||||
cln::cl_I factor = cln::expt_pos( base , exponent ) ;
|
||||
cln::cl_I product = factor * factor ;
|
||||
std::cout << "The result of 2^64 * 2^64 is " << product << " !\n" ;
|
||||
return 0 ;
|
||||
}
|
||||
55
Task/Long-multiplication/C/long-multiplication-1.c
Normal file
55
Task/Long-multiplication/C/long-multiplication-1.c
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* c = a * b. Caller is responsible for memory.
|
||||
c must not be the same as either a or b. */
|
||||
void longmulti(const char *a, const char *b, char *c)
|
||||
{
|
||||
int i = 0, j = 0, k = 0, n, carry;
|
||||
int la, lb;
|
||||
|
||||
/* either is zero, return "0" */
|
||||
if (!strcmp(a, "0") || !strcmp(b, "0")) {
|
||||
c[0] = '0', c[1] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
/* see if either a or b is negative */
|
||||
if (a[0] == '-') { i = 1; k = !k; }
|
||||
if (b[0] == '-') { j = 1; k = !k; }
|
||||
|
||||
/* if yes, prepend minus sign if needed and skip the sign */
|
||||
if (i || j) {
|
||||
if (k) c[0] = '-';
|
||||
longmulti(a + i, b + j, c + k);
|
||||
return;
|
||||
}
|
||||
|
||||
la = strlen(a);
|
||||
lb = strlen(b);
|
||||
memset(c, '0', la + lb);
|
||||
c[la + lb] = '\0';
|
||||
|
||||
# define I(a) (a - '0')
|
||||
for (i = la - 1; i >= 0; i--) {
|
||||
for (j = lb - 1, k = i + j + 1, carry = 0; j >= 0; j--, k--) {
|
||||
n = I(a[i]) * I(b[j]) + I(c[k]) + carry;
|
||||
carry = n / 10;
|
||||
c[k] = (n % 10) + '0';
|
||||
}
|
||||
c[k] += carry;
|
||||
}
|
||||
# undef I
|
||||
if (c[0] == '0') memmove(c, c + 1, la + lb);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
char c[1024];
|
||||
longmulti("-18446744073709551616", "-18446744073709551616", c);
|
||||
printf("%s\n", c);
|
||||
|
||||
return 0;
|
||||
}
|
||||
1
Task/Long-multiplication/C/long-multiplication-2.c
Normal file
1
Task/Long-multiplication/C/long-multiplication-2.c
Normal file
|
|
@ -0,0 +1 @@
|
|||
340282366920938463463374607431768211456
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
# This very limited BCD-based collection of functions
|
||||
# allows for long multiplication. It works for positive
|
||||
# numbers only. The assumed data structure is as follows:
|
||||
# BcdInteger.from_integer(4321) == [1, 2, 3, 4]
|
||||
|
||||
BcdInteger =
|
||||
from_string: (s) ->
|
||||
arr = []
|
||||
for c in s
|
||||
arr.unshift parseInt(c)
|
||||
arr
|
||||
|
||||
from_integer: (n) ->
|
||||
result = []
|
||||
while n > 0
|
||||
result.push n % 10
|
||||
n = Math.floor n / 10
|
||||
result
|
||||
|
||||
to_string: (arr) ->
|
||||
s = ''
|
||||
for elem in arr
|
||||
s = elem.toString() + s
|
||||
s
|
||||
|
||||
sum: (arr1, arr2) ->
|
||||
if arr1.length < arr2.length
|
||||
return BcdInteger.sum(arr2, arr1)
|
||||
carry = 0
|
||||
result= []
|
||||
for d1, pos in arr1
|
||||
d = d1 + (arr2[pos] || 0) + carry
|
||||
result.push d % 10
|
||||
carry = Math.floor d / 10
|
||||
if carry
|
||||
result.push 1
|
||||
result
|
||||
|
||||
multiply_by_power_of_ten: (arr, power_of_ten) ->
|
||||
result = (0 for i in [0...power_of_ten])
|
||||
result.concat arr
|
||||
|
||||
product_by_integer: (arr, n) ->
|
||||
result = []
|
||||
for digit, i in arr
|
||||
prod = BcdInteger.from_integer n * digit
|
||||
prod = BcdInteger.multiply_by_power_of_ten prod, i
|
||||
result = BcdInteger.sum result, prod
|
||||
result
|
||||
|
||||
product: (arr1, arr2) ->
|
||||
result = []
|
||||
for digit, i in arr1
|
||||
prod = BcdInteger.product_by_integer arr2, digit
|
||||
prod = BcdInteger.multiply_by_power_of_ten prod, i
|
||||
result = BcdInteger.sum result, prod
|
||||
result
|
||||
|
||||
x = BcdInteger.from_integer 1
|
||||
for i in [1..64]
|
||||
x = BcdInteger.product_by_integer x, 2
|
||||
console.log BcdInteger.to_string x # 18446744073709551616
|
||||
square = BcdInteger.product x, x
|
||||
console.log BcdInteger.to_string square # 340282366920938463463374607431768211456
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
(defun number->digits (number)
|
||||
(do ((digits '())) ((zerop number) digits)
|
||||
(multiple-value-bind (quotient remainder) (floor number 10)
|
||||
(setf number quotient)
|
||||
(push remainder digits))))
|
||||
|
||||
(defun digits->number (digits)
|
||||
(reduce #'(lambda (n d) (+ (* 10 n) d)) digits :initial-value 0))
|
||||
|
||||
(defun long-multiply (a b)
|
||||
(labels ((first-digit (list)
|
||||
"0 if list is empty, else first element of list."
|
||||
(if (endp list) 0
|
||||
(first list)))
|
||||
(long-add (digitses &optional (carry 0) (sum '()))
|
||||
"Do long addition on the list of lists of digits. Each
|
||||
list of digits in digitses should begin with the least
|
||||
significant digit. This is the opposite of the digit
|
||||
list returned by number->digits which places the most
|
||||
significant digit first. The digits returned by
|
||||
long-add do have the most significant bit first."
|
||||
(if (every 'endp digitses)
|
||||
(nconc (digits carry) sum)
|
||||
(let ((column-sum (reduce '+ (mapcar #'first-digit digitses)
|
||||
:initial-value carry)))
|
||||
(multiple-value-bind (carry column-digit)
|
||||
(floor column-sum 10)
|
||||
(long-add (mapcar 'rest digitses)
|
||||
carry (list* column-digit sum)))))))
|
||||
;; get the digits of a and b (least significant bit first), and
|
||||
;; compute the zero padded rows. Then, add these rows (using
|
||||
;; long-add) and convert the digits back to a number.
|
||||
(do ((a (nreverse (digits a)))
|
||||
(b (nreverse (digits b)))
|
||||
(prefix '() (list* 0 prefix))
|
||||
(rows '()))
|
||||
((endp b) (digits->number (long-add rows)))
|
||||
(let* ((bi (pop b))
|
||||
(row (mapcar #'(lambda (ai) (* ai bi)) a)))
|
||||
(push (append prefix row) rows)))))
|
||||
5
Task/Long-multiplication/D/long-multiplication-1.d
Normal file
5
Task/Long-multiplication/D/long-multiplication-1.d
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import std.stdio, std.bigint;
|
||||
|
||||
void main() {
|
||||
writeln(BigInt(2) ^^ 64 * BigInt(2) ^^ 64);
|
||||
}
|
||||
29
Task/Long-multiplication/D/long-multiplication-2.d
Normal file
29
Task/Long-multiplication/D/long-multiplication-2.d
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import std.stdio, std.algorithm, std.range;
|
||||
|
||||
auto longMult(in string x, in string y) /*pure nothrow*/ {
|
||||
auto digits1 = x.retro().map!q{a - '0'}();
|
||||
const digits2 = y.retro().map!q{a - '0'}().array();
|
||||
int[] res;
|
||||
|
||||
foreach (i, d1; int.max.iota().zip(digits1))
|
||||
foreach (j, d2; digits2) {
|
||||
immutable int k = i + j;
|
||||
if (res.length <= k)
|
||||
res.length += 1;
|
||||
res[k] += d1 * d2;
|
||||
|
||||
if (res[k] > 9) {
|
||||
if (res.length <= k + 1)
|
||||
res.length += 1;
|
||||
res[k + 1] = res[k] / 10 + res[k + 1];
|
||||
res[k] -= res[k] / 10 * 10;
|
||||
}
|
||||
}
|
||||
|
||||
return res.retro().map!q{ cast(char)(a + '0') }();
|
||||
}
|
||||
|
||||
void main() {
|
||||
immutable two64 = "18446744073709551616";
|
||||
writeln(longMult(two64, two64));
|
||||
}
|
||||
1
Task/Long-multiplication/Dc/long-multiplication.dc
Normal file
1
Task/Long-multiplication/Dc/long-multiplication.dc
Normal file
|
|
@ -0,0 +1 @@
|
|||
2 64^ 2 64^ *p
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
constant base = 1000000000
|
||||
|
||||
function atom_to_long(atom a)
|
||||
sequence s
|
||||
s = {}
|
||||
while a>0 do
|
||||
s = append(s,remainder(a,base))
|
||||
a = floor(a/base)
|
||||
end while
|
||||
return s
|
||||
end function
|
||||
|
||||
function long_mult(object a, object b)
|
||||
sequence c
|
||||
if atom(a) then
|
||||
a = atom_to_long(a)
|
||||
end if
|
||||
if atom(b) then
|
||||
b = atom_to_long(b)
|
||||
end if
|
||||
c = repeat(0,length(a)+length(b))
|
||||
for i = 1 to length(a) do
|
||||
c[i .. i+length(b)-1] += a[i]*b
|
||||
end for
|
||||
|
||||
for i = 1 to length(c) do
|
||||
if c[i] > base then
|
||||
c[i+1] += floor(c[i]/base) -- carry
|
||||
c[i] = remainder(c[i],base)
|
||||
end if
|
||||
end for
|
||||
|
||||
if c[$] = 0 then
|
||||
c = c[1..$-1]
|
||||
end if
|
||||
return c
|
||||
end function
|
||||
|
||||
|
||||
function long_to_str(sequence a)
|
||||
sequence s
|
||||
s = sprintf("%d",a[$])
|
||||
for i = length(a)-1 to 1 by -1 do
|
||||
s &= sprintf("%09d",a[i])
|
||||
end for
|
||||
return s
|
||||
end function
|
||||
|
||||
sequence a, b, c
|
||||
|
||||
a = atom_to_long(power(2,32))
|
||||
printf(1,"a is %s\n",{long_to_str(a)})
|
||||
|
||||
b = long_mult(a,a)
|
||||
printf(1,"a*a is %s\n",{long_to_str(b)})
|
||||
|
||||
c = long_mult(b,b)
|
||||
printf(1,"a*a*a*a is %s\n",{long_to_str(c)})
|
||||
12
Task/Long-multiplication/Factor/long-multiplication-1.factor
Normal file
12
Task/Long-multiplication/Factor/long-multiplication-1.factor
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
USING: kernel math sequences ;
|
||||
|
||||
: longmult-seq ( xs ys -- zs )
|
||||
[ * ] cartesian-map
|
||||
dup length iota [ 0 <repetition> ] map
|
||||
[ prepend ] 2map
|
||||
[ ] [ [ 0 suffix ] dip [ + ] 2map ] map-reduce ;
|
||||
|
||||
: integer->digits ( x -- xs ) { } swap [ dup 0 > ] [ 10 /mod swap [ prefix ] dip ] while drop ;
|
||||
: digits->integer ( xs -- x ) 0 [ swap 10 * + ] reduce ;
|
||||
|
||||
: longmult ( x y -- z ) [ integer->digits ] bi@ longmult-seq digits->integer ;
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
( scratchpad ) 2 64 ^ dup longmult .
|
||||
340282366920938463463374607431768211456
|
||||
( scratchpad ) 2 64 ^ dup * .
|
||||
340282366920938463463374607431768211456
|
||||
75
Task/Long-multiplication/Fortran/long-multiplication-1.f
Normal file
75
Task/Long-multiplication/Fortran/long-multiplication-1.f
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
module LongMoltiplication
|
||||
implicit none
|
||||
|
||||
type longnum
|
||||
integer, dimension(:), pointer :: num
|
||||
end type longnum
|
||||
|
||||
interface operator (*)
|
||||
module procedure longmolt_ll
|
||||
end interface
|
||||
|
||||
contains
|
||||
|
||||
subroutine longmolt_s2l(istring, num)
|
||||
character(len=*), intent(in) :: istring
|
||||
type(longnum), intent(out) :: num
|
||||
|
||||
integer :: i, l
|
||||
|
||||
l = len(istring)
|
||||
|
||||
allocate(num%num(l))
|
||||
|
||||
forall(i=1:l) num%num(l-i+1) = iachar(istring(i:i)) - 48
|
||||
|
||||
end subroutine longmolt_s2l
|
||||
|
||||
! this one performs the moltiplication
|
||||
function longmolt_ll(a, b) result(c)
|
||||
type(longnum) :: c
|
||||
type(longnum), intent(in) :: a, b
|
||||
|
||||
integer, dimension(:,:), allocatable :: t
|
||||
integer :: ntlen, i, j
|
||||
|
||||
ntlen = size(a%num) + size(b%num) + 1
|
||||
allocate(c%num(ntlen))
|
||||
c%num = 0
|
||||
|
||||
allocate(t(size(b%num), ntlen))
|
||||
|
||||
t = 0
|
||||
forall(i=1:size(b%num), j=1:size(a%num)) t(i, j+i-1) = b%num(i) * a%num(j)
|
||||
|
||||
do j=2, ntlen
|
||||
forall(i=1:size(b%num)) t(i, j) = t(i, j) + t(i, j-1)/10
|
||||
end do
|
||||
|
||||
forall(j=1:ntlen) c%num(j) = sum(mod(t(:,j), 10))
|
||||
|
||||
do j=2, ntlen
|
||||
c%num(j) = c%num(j) + c%num(j-1)/10
|
||||
end do
|
||||
|
||||
c%num = mod(c%num, 10)
|
||||
|
||||
deallocate(t)
|
||||
end function longmolt_ll
|
||||
|
||||
|
||||
subroutine longmolt_print(num)
|
||||
type(longnum), intent(in) :: num
|
||||
|
||||
integer :: i, j
|
||||
|
||||
do j=size(num%num), 2, -1
|
||||
if ( num%num(j) /= 0 ) exit
|
||||
end do
|
||||
|
||||
do i=j, 1, -1
|
||||
write(*,"(I1)", advance="no") num%num(i)
|
||||
end do
|
||||
end subroutine longmolt_print
|
||||
|
||||
end module LongMoltiplication
|
||||
13
Task/Long-multiplication/Fortran/long-multiplication-2.f
Normal file
13
Task/Long-multiplication/Fortran/long-multiplication-2.f
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
program Test
|
||||
use LongMoltiplication
|
||||
|
||||
type(longnum) :: a, b, r
|
||||
|
||||
call longmolt_s2l("18446744073709551616", a)
|
||||
call longmolt_s2l("18446744073709551616", b)
|
||||
|
||||
r = a * b
|
||||
call longmolt_print(r)
|
||||
write(*,*)
|
||||
|
||||
end program Test
|
||||
79
Task/Long-multiplication/Go/long-multiplication.go
Normal file
79
Task/Long-multiplication/Go/long-multiplication.go
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
// Long multiplication per WP article referenced by task description.
|
||||
// That is, multiplicand is multiplied by single digits of multiplier
|
||||
// to form intermediate results. Intermediate results are accumulated
|
||||
// for the product. Used here is the abacus method mentioned by the
|
||||
// article, of summing intermediate results as they are produced,
|
||||
// rather than all at once at the end.
|
||||
//
|
||||
// Limitations: Negative numbers not supported, superfluous leading zeros
|
||||
// not generally removed.
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// argument validation
|
||||
func d(b byte) byte {
|
||||
if b < '0' || b > '9' {
|
||||
panic("digit 0-9 expected")
|
||||
}
|
||||
return b - '0'
|
||||
}
|
||||
|
||||
// add two numbers as strings
|
||||
func add(x, y string) string {
|
||||
if len(y) > len(x) {
|
||||
x, y = y, x
|
||||
}
|
||||
b := make([]byte, len(x)+1)
|
||||
var c byte
|
||||
for i := 1; i <= len(x); i++ {
|
||||
if i <= len(y) {
|
||||
c += d(y[len(y)-i])
|
||||
}
|
||||
s := d(x[len(x)-i]) + c
|
||||
c = s / 10
|
||||
b[len(b)-i] = (s % 10) + '0'
|
||||
}
|
||||
if c == 0 {
|
||||
return string(b[1:])
|
||||
}
|
||||
b[0] = c + '0'
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// multipy a number by a single digit
|
||||
func mulDigit(x string, y byte) string {
|
||||
if y == '0' {
|
||||
return "0"
|
||||
}
|
||||
y = d(y)
|
||||
b := make([]byte, len(x)+1)
|
||||
var c byte
|
||||
for i := 1; i <= len(x); i++ {
|
||||
s := d(x[len(x)-i])*y + c
|
||||
c = s / 10
|
||||
b[len(b)-i] = (s % 10) + '0'
|
||||
}
|
||||
if c == 0 {
|
||||
return string(b[1:])
|
||||
}
|
||||
b[0] = c + '0'
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// multiply two numbers as strings
|
||||
func mul(x, y string) string {
|
||||
result := mulDigit(x, y[len(y)-1])
|
||||
for i, zeros := 2, ""; i <= len(y); i++ {
|
||||
zeros += "0"
|
||||
result = add(result, mulDigit(x, y[len(y)-i])+zeros)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// requested output
|
||||
const n = "18446744073709551616"
|
||||
|
||||
func main() {
|
||||
fmt.Println(mul(n, n))
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
println 2**64 * 2**64
|
||||
10
Task/Long-multiplication/Haskell/long-multiplication-1.hs
Normal file
10
Task/Long-multiplication/Haskell/long-multiplication-1.hs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
digits :: Integer -> [Integer]
|
||||
digits = map (fromIntegral.digitToInt) . show
|
||||
|
||||
lZZ = inits $ repeat 0
|
||||
|
||||
table f = map . flip (map . f)
|
||||
|
||||
polymul = ((map sum . transpose . zipWith (++) lZZ) .) . table (*)
|
||||
|
||||
longmult = (foldl1 ((+) . (10 *)) .) . (. digits) . polymul . digits
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
*Main> (2^64) `longmult` (2^64)
|
||||
340282366920938463463374607431768211456
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
procedure main()
|
||||
write(2^64*2^64)
|
||||
end
|
||||
5
Task/Long-multiplication/J/long-multiplication-1.j
Normal file
5
Task/Long-multiplication/J/long-multiplication-1.j
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
digits =: ,.&.":
|
||||
polymult =: +//.@(*/)
|
||||
buildDecimal=: 10x&#.
|
||||
|
||||
longmult=: buildDecimal@polymult&digits
|
||||
2
Task/Long-multiplication/J/long-multiplication-2.j
Normal file
2
Task/Long-multiplication/J/long-multiplication-2.j
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
longmult~ 2x^64
|
||||
340282366920938463463374607431768211456
|
||||
1
Task/Long-multiplication/J/long-multiplication-3.j
Normal file
1
Task/Long-multiplication/J/long-multiplication-3.j
Normal file
|
|
@ -0,0 +1 @@
|
|||
longmult=: 10x&#.@(+//.@(*/)&(,.&.":))
|
||||
2
Task/Long-multiplication/J/long-multiplication-4.j
Normal file
2
Task/Long-multiplication/J/long-multiplication-4.j
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
10x&#.@(+//.@(*/)&(,.&.":))~2x^64
|
||||
340282366920938463463374607431768211456
|
||||
2
Task/Long-multiplication/J/long-multiplication-5.j
Normal file
2
Task/Long-multiplication/J/long-multiplication-5.j
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
(+ 10x&*)/@|.@(+//.@(*/)&(,.&.":))~2x^64
|
||||
340282366920938463463374607431768211456
|
||||
2
Task/Long-multiplication/J/long-multiplication-6.j
Normal file
2
Task/Long-multiplication/J/long-multiplication-6.j
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
(2x^64)*(2x^64)
|
||||
340282366920938463463374607431768211456
|
||||
2
Task/Long-multiplication/J/long-multiplication-7.j
Normal file
2
Task/Long-multiplication/J/long-multiplication-7.j
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
,.&.": 123
|
||||
1 2 3
|
||||
2
Task/Long-multiplication/J/long-multiplication-8.j
Normal file
2
Task/Long-multiplication/J/long-multiplication-8.j
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
1 2 3 (+//.@(*/)) 1 2 3
|
||||
1 4 10 12 9
|
||||
2
Task/Long-multiplication/J/long-multiplication-9.j
Normal file
2
Task/Long-multiplication/J/long-multiplication-9.j
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
(+ 10x&*)/|. 1 4 10 12 9
|
||||
15129
|
||||
13
Task/Long-multiplication/Java/long-multiplication.java
Normal file
13
Task/Long-multiplication/Java/long-multiplication.java
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import java.math.BigInteger;
|
||||
|
||||
public class LongMult {
|
||||
|
||||
public static void main(String[] args) {
|
||||
BigInteger TwoPow64 = new BigInteger("18446744073709551616");
|
||||
System.out.println(mult(TwoPow64, TwoPow64));
|
||||
}
|
||||
|
||||
public static BigInteger mult(BigInteger a, BigInteger b){
|
||||
return a.multiply(b);
|
||||
}
|
||||
}
|
||||
18
Task/Long-multiplication/JavaScript/long-multiplication.js
Normal file
18
Task/Long-multiplication/JavaScript/long-multiplication.js
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
function mult(num1,num2){
|
||||
var a1 = num1.split("").reverse();
|
||||
var a2 = num2.split("").reverse();
|
||||
var aResult = new Array;
|
||||
|
||||
for ( iterNum1 = 0; iterNum1 < a1.length; iterNum1++ ) {
|
||||
for ( iterNum2 = 0; iterNum2 < a2.length; iterNum2++ ) {
|
||||
idxIter = iterNum1 + iterNum2; // Get the current array position.
|
||||
aResult[idxIter] = a1[iterNum1] * a2[iterNum2] + ( idxIter >= aResult.length ? 0 : aResult[idxIter] );
|
||||
|
||||
if ( aResult[idxIter] > 9 ) { // Carrying
|
||||
aResult[idxIter + 1] = Math.floor( aResult[idxIter] / 10 ) + ( idxIter + 1 >= aResult.length ? 0 : aResult[idxIter + 1] );
|
||||
aResult[idxIter] -= Math.floor( aResult[idxIter] / 10 ) * 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
return aResult.reverse().join("");
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
print 2^64 *2^64
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
LongMultiplication[a_,b_]:=Module[{d1,d2},
|
||||
d1=IntegerDigits[a]//Reverse;
|
||||
d2=IntegerDigits[b]//Reverse;
|
||||
Sum[d1[[i]]d2[[j]]*10^(i+j-2),{i,1,Length[d1]},{j,1,Length[d2]}]
|
||||
]
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
n1 = 2^64;
|
||||
n2 = 2^64;
|
||||
LongMultiplication[n1, n2]
|
||||
|
|
@ -0,0 +1 @@
|
|||
340282366920938463463374607431768211456
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
n1=2^8000;
|
||||
n2=2^8000;
|
||||
Timing[LongMultiplication[n1,n2]][[1]]
|
||||
Timing[n1 n2][[1]]
|
||||
Floor[%%/%]
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
72.9686
|
||||
7.*10^-6
|
||||
10424088
|
||||
6
Task/Long-multiplication/PHP/long-multiplication.php
Normal file
6
Task/Long-multiplication/PHP/long-multiplication.php
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
|
||||
$factor = bcpow(2, 64);
|
||||
$product = bcmul($factor, $factor);
|
||||
echo "2^64 * 2^64 is " . $product;
|
||||
?>
|
||||
55
Task/Long-multiplication/Perl/long-multiplication.pl
Normal file
55
Task/Long-multiplication/Perl/long-multiplication.pl
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#!/usr/bin/perl -w
|
||||
use strict;
|
||||
|
||||
# This should probably be done in a loop rather than be recursive.
|
||||
sub add_with_carry
|
||||
{
|
||||
my $resultref = shift;
|
||||
my $addend = shift;
|
||||
my $addendpos = shift;
|
||||
|
||||
push @$resultref, (0) while (scalar @$resultref < $addendpos + 1);
|
||||
my $addend_result = $addend + $resultref->[$addendpos];
|
||||
my @addend_digits = reverse split //, $addend_result;
|
||||
$resultref->[$addendpos] = shift @addend_digits;
|
||||
|
||||
my $carry_digit = shift @addend_digits;
|
||||
&add_with_carry($resultref, $carry_digit, $addendpos + 1)
|
||||
if( defined $carry_digit )
|
||||
}
|
||||
|
||||
sub longhand_multiplication
|
||||
{
|
||||
my @multiplicand = reverse split //, shift;
|
||||
my @multiplier = reverse split //, shift;
|
||||
my @result = ();
|
||||
my $multiplicand_offset = 0;
|
||||
foreach my $multiplicand_digit (@multiplicand)
|
||||
{
|
||||
my $multiplier_offset = $multiplicand_offset;
|
||||
foreach my $multiplier_digit (@multiplier)
|
||||
{
|
||||
my $multiplication_result = $multiplicand_digit * $multiplier_digit;
|
||||
my @result_digit_addend_list = reverse split //, $multiplication_result;
|
||||
|
||||
my $addend_offset = $multiplier_offset;
|
||||
foreach my $result_digit_addend (@result_digit_addend_list)
|
||||
{
|
||||
&add_with_carry(\@result, $result_digit_addend, $addend_offset++)
|
||||
}
|
||||
|
||||
++$multiplier_offset;
|
||||
}
|
||||
|
||||
++$multiplicand_offset;
|
||||
}
|
||||
|
||||
@result = reverse @result;
|
||||
|
||||
return join '', @result;
|
||||
}
|
||||
|
||||
my $sixtyfour = "18446744073709551616";
|
||||
|
||||
my $onetwentyeight = &longhand_multiplication($sixtyfour, $sixtyfour);
|
||||
print "$onetwentyeight\n";
|
||||
2
Task/Long-multiplication/PicoLisp/long-multiplication.l
Normal file
2
Task/Long-multiplication/PicoLisp/long-multiplication.l
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
: (* (** 2 64) (** 2 64))
|
||||
-> 340282366920938463463374607431768211456
|
||||
2
Task/Long-multiplication/Prolog/long-multiplication.pro
Normal file
2
Task/Long-multiplication/Prolog/long-multiplication.pro
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
?- X is 2**64 * 2**64.
|
||||
X = 340282366920938463463374607431768211456.
|
||||
2
Task/Long-multiplication/Python/long-multiplication-1.py
Normal file
2
Task/Long-multiplication/Python/long-multiplication-1.py
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
#!/usr/bin/env python
|
||||
print 2**64*2**64
|
||||
33
Task/Long-multiplication/Python/long-multiplication-2.py
Normal file
33
Task/Long-multiplication/Python/long-multiplication-2.py
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
def add_with_carry(result, addend, addendpos):
|
||||
while True:
|
||||
while len(result) < addendpos + 1:
|
||||
result.append(0)
|
||||
addend_result = str(int(addend) + int(result[addendpos]))
|
||||
addend_digits = list(addend_result)
|
||||
result[addendpos] = addend_digits.pop()
|
||||
|
||||
if not addend_digits:
|
||||
break
|
||||
addend = addend_digits.pop()
|
||||
addendpos += 1
|
||||
|
||||
def longhand_multiplication(multiplicand, multiplier):
|
||||
result = []
|
||||
for multiplicand_offset, multiplicand_digit in enumerate(reversed(multiplicand)):
|
||||
for multiplier_offset, multiplier_digit in enumerate(reversed(multiplier), start=multiplicand_offset):
|
||||
multiplication_result = str(int(multiplicand_digit) * int(multiplier_digit))
|
||||
|
||||
for addend_offset, result_digit_addend in enumerate(reversed(multiplication_result), start=multiplier_offset):
|
||||
add_with_carry(result, result_digit_addend, addend_offset)
|
||||
|
||||
result.reverse()
|
||||
|
||||
return ''.join(result)
|
||||
|
||||
if __name__ == "__main__":
|
||||
sixtyfour = "18446744073709551616"
|
||||
|
||||
onetwentyeight = longhand_multiplication(sixtyfour, sixtyfour)
|
||||
print(onetwentyeight)
|
||||
20
Task/Long-multiplication/Python/long-multiplication-3.py
Normal file
20
Task/Long-multiplication/Python/long-multiplication-3.py
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
def digits(x):
|
||||
return [int(c) for c in str(x)]
|
||||
|
||||
def mult_table(xs, ys):
|
||||
return [[x * y for x in xs] for y in ys]
|
||||
|
||||
def polymul(xs, ys):
|
||||
return map(lambda *vs: sum(filter(None, vs)),
|
||||
*[[0] * i + zs for i, zs in enumerate(mult_table(xs, ys))])
|
||||
|
||||
def longmult(x, y):
|
||||
result = 0
|
||||
for v in polymul(digits(x), digits(y)):
|
||||
result = result * 10 + v
|
||||
return result
|
||||
|
||||
if __name__ == "__main__":
|
||||
print longmult(2**64, 2**64)
|
||||
3
Task/Long-multiplication/R/long-multiplication-1.r
Normal file
3
Task/Long-multiplication/R/long-multiplication-1.r
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
library(gmp)
|
||||
a <- as.bigz("18446744073709551616")
|
||||
mul.bigz(a,a)
|
||||
66
Task/Long-multiplication/R/long-multiplication-2.r
Normal file
66
Task/Long-multiplication/R/long-multiplication-2.r
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
longmult <- function(xstr, ystr)
|
||||
{
|
||||
#get the number described in each string
|
||||
getnumeric <- function(xstr) as.numeric(unlist(strsplit(xstr, "")))
|
||||
|
||||
x <- getnumeric(xstr)
|
||||
y <- getnumeric(ystr)
|
||||
|
||||
#multiply each pair of digits together
|
||||
mat <- apply(x %o% y, 1, as.character)
|
||||
|
||||
#loop over columns, then rows, adding zeroes to end of each number in the matrix to get the correct positioning
|
||||
ncols <- ncol(mat)
|
||||
cols <- seq_len(ncols)
|
||||
for(j in cols)
|
||||
{
|
||||
zeroes <- paste(rep("0", ncols-j), collapse="")
|
||||
mat[,j] <- paste(mat[,j], zeroes, sep="")
|
||||
}
|
||||
|
||||
nrows <- nrow(mat)
|
||||
rows <- seq_len(nrows)
|
||||
for(i in rows)
|
||||
{
|
||||
zeroes <- paste(rep("0", nrows-i), collapse="")
|
||||
mat[i,] <- paste(mat[i,], zeroes, sep="")
|
||||
}
|
||||
|
||||
#add zeroes to the start of the each number, so they are all the same length
|
||||
len <- max(nchar(mat))
|
||||
strcolumns <- formatC(cbind(as.vector(mat)), width=len)
|
||||
strcolumns <- gsub(" ", "0", strcolumns)
|
||||
|
||||
#line up all the numbers below each other
|
||||
strmat <- matrix(unlist(strsplit(strcolumns, "")), byrow=TRUE, ncol=len)
|
||||
|
||||
#convert to numeric and add them
|
||||
mat2 <- apply(strmat, 2, as.numeric)
|
||||
sum1 <- colSums(mat2)
|
||||
|
||||
#repeat the process on each of the totals, until each total is a single digit
|
||||
repeat
|
||||
{
|
||||
ntotals <- length(sum1)
|
||||
totals <- seq_len(ntotals)
|
||||
for(i in totals)
|
||||
{
|
||||
zeroes <- paste(rep("0", ntotals-i), collapse="")
|
||||
sum1[i] <- paste(sum1[i], zeroes, sep="")
|
||||
}
|
||||
len2 <- max(nchar(sum1))
|
||||
strcolumns2 <- formatC(cbind(as.vector(sum1)), width=len2)
|
||||
strcolumns2 <- gsub(" ", "0", strcolumns2)
|
||||
strmat2 <- matrix(unlist(strsplit(strcolumns2, "")), byrow=TRUE, ncol=len2)
|
||||
mat3 <- apply(strmat2, 2, as.numeric)
|
||||
sum1 <- colSums(mat3)
|
||||
if(all(sum1 < 10)) break
|
||||
}
|
||||
|
||||
#Concatenate the digits together
|
||||
ans <- paste(sum1, collapse="")
|
||||
ans
|
||||
}
|
||||
|
||||
a <- "18446744073709551616"
|
||||
longmult(a, a)
|
||||
4
Task/Long-multiplication/REXX/long-multiplication.rexx
Normal file
4
Task/Long-multiplication/REXX/long-multiplication.rexx
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
/*REXX program to use and show large multiplication results. */
|
||||
numeric digits 1000 /*up to around 8 meg is feasible.*/
|
||||
say '2^64 * 2^64 = ' 2**64 * 2**64
|
||||
say '2^64 * 2^64 * 2^128 = ' (2**64) * (2**64) * (2**128)
|
||||
33
Task/Long-multiplication/Ruby/long-multiplication.rb
Normal file
33
Task/Long-multiplication/Ruby/long-multiplication.rb
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
def longmult(x,y)
|
||||
digits = reverse_split_number(x)
|
||||
result = [0]
|
||||
j = 0
|
||||
reverse_split_number(y).each do |m|
|
||||
c = 0
|
||||
i = j
|
||||
digits.each do |d|
|
||||
v = result[i]
|
||||
result << 0 if v.zero?
|
||||
c, v = (v + c + d*m).divmod(10)
|
||||
result[i] = v
|
||||
i += 1
|
||||
end
|
||||
result[i] += c
|
||||
j += 1
|
||||
end
|
||||
# calculate the answer from the result array of digits
|
||||
result.reverse.inject(0) {|sum, n| 10*sum + n}
|
||||
end
|
||||
|
||||
def reverse_split_number(m)
|
||||
digits = []
|
||||
while m > 0
|
||||
m, v = m.divmod 10
|
||||
digits << v
|
||||
end
|
||||
digits
|
||||
end
|
||||
|
||||
n=2**64
|
||||
printf " %d * %d = %d\n", n, n, n*n
|
||||
printf "longmult(%d, %d) = %d\n", n, n, longmult(n,n)
|
||||
23
Task/Long-multiplication/Scala/long-multiplication-1.scala
Normal file
23
Task/Long-multiplication/Scala/long-multiplication-1.scala
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
def addNums(x: String, y: String) = {
|
||||
val padSize = x.length max y.length
|
||||
val paddedX = "0" * (padSize - x.length) + x
|
||||
val paddedY = "0" * (padSize - y.length) + y
|
||||
val (sum, carry) = (paddedX zip paddedY).foldRight(("", 0)) {
|
||||
case ((dx, dy), (acc, carry)) =>
|
||||
val sum = dx.asDigit + dy.asDigit + carry
|
||||
((sum % 10).toString + acc, sum / 10)
|
||||
}
|
||||
if (carry != 0) carry.toString + sum else sum
|
||||
}
|
||||
|
||||
def multByDigit(num: String, digit: Int) = {
|
||||
val (mult, carry) = num.foldRight(("", 0)) {
|
||||
case (d, (acc, carry)) =>
|
||||
val mult = d.asDigit * digit + carry
|
||||
((mult % 10).toString + acc, mult / 10)
|
||||
}
|
||||
if (carry != 0) carry.toString + mult else mult
|
||||
}
|
||||
|
||||
def mult(x: String, y: String) =
|
||||
y.foldLeft("")((acc, digit) => addNums(acc + "0", multByDigit(x, digit.asDigit)))
|
||||
22
Task/Long-multiplication/Scala/long-multiplication-2.scala
Normal file
22
Task/Long-multiplication/Scala/long-multiplication-2.scala
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
def adjustResult(result: IndexedSeq[Int]) = (
|
||||
result
|
||||
.map(_ % 10) // remove carry from each digit
|
||||
.tail // drop the seed carry
|
||||
.reverse // put most significant digits on the left
|
||||
.dropWhile(_ == 0) // remove leading zeroes
|
||||
.mkString
|
||||
)
|
||||
|
||||
def addNums(x: String, y: String) = {
|
||||
val padSize = (x.length max y.length) + 1 // We want to keep a zero to the left, to catch the carry
|
||||
val paddedX = "0" * (padSize - x.length) + x
|
||||
val paddedY = "0" * (padSize - y.length) + y
|
||||
adjustResult((paddedX zip paddedY).scanRight(0) {
|
||||
case ((dx, dy), last) => dx.asDigit + dy.asDigit + last / 10
|
||||
})
|
||||
}
|
||||
|
||||
def multByDigit(num: String, digit: Int) = adjustResult(("0"+num).scanRight(0)(_.asDigit * digit + _ / 10))
|
||||
|
||||
def mult(x: String, y: String) =
|
||||
y.foldLeft("")((acc, digit) => addNums(acc + "0", multByDigit(x, digit.asDigit)))
|
||||
1
Task/Long-multiplication/Scheme/long-multiplication.ss
Normal file
1
Task/Long-multiplication/Scheme/long-multiplication.ss
Normal file
|
|
@ -0,0 +1 @@
|
|||
(* (expt 2 64) (expt 2 64))
|
||||
|
|
@ -0,0 +1 @@
|
|||
(2 raisedTo: 64) * (2 raisedTo: 64).
|
||||
28
Task/Long-multiplication/Tcl/long-multiplication.tcl
Normal file
28
Task/Long-multiplication/Tcl/long-multiplication.tcl
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
package require Tcl 8.5
|
||||
|
||||
proc longmult {x y} {
|
||||
set digits [lreverse [split $x ""]]
|
||||
set result {0}
|
||||
set j -2
|
||||
foreach m [lreverse [split $y ""]] {
|
||||
set c 0
|
||||
set i [incr j]
|
||||
foreach d $digits {
|
||||
set v [lindex $result [incr i]]
|
||||
if {$v eq ""} {
|
||||
lappend result 0
|
||||
set v 0
|
||||
}
|
||||
regexp (.)(.)$ 0[expr {$v + $c + $d*$m}] -> c v
|
||||
lset result $i $v
|
||||
}
|
||||
lappend result $c
|
||||
}
|
||||
# Reconvert digit list into a decimal number
|
||||
set result [string trimleft [join [lreverse $result] ""] 0]
|
||||
if {$result == ""} then {return 0} else {return $result}
|
||||
}
|
||||
|
||||
puts [set n [expr {2**64}]]
|
||||
puts [longmult $n $n]
|
||||
puts [expr {$n * $n}]
|
||||
Loading…
Add table
Add a link
Reference in a new issue