This commit is contained in:
Ingy döt Net 2013-04-10 21:29:02 -07:00
parent 764da6cbbb
commit db842d013d
19005 changed files with 197040 additions and 7 deletions

View 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

View file

@ -0,0 +1,2 @@
---
note: Arbitrary precision

View 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))
)

View 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
);

View 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
);

View 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))
)

View 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 "===="
}
}

View 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;

View 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;

View 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;

View 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 "*";

View 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;

View 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;

View 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)
}

View 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

View 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"

View file

@ -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$)

View 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)

View 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 ;
}

View 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;
}

View file

@ -0,0 +1 @@
340282366920938463463374607431768211456

View file

@ -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

View file

@ -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)))))

View file

@ -0,0 +1,5 @@
import std.stdio, std.bigint;
void main() {
writeln(BigInt(2) ^^ 64 * BigInt(2) ^^ 64);
}

View 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));
}

View file

@ -0,0 +1 @@
2 64^ 2 64^ *p

View file

@ -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)})

View 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 ;

View file

@ -0,0 +1,4 @@
( scratchpad ) 2 64 ^ dup longmult .
340282366920938463463374607431768211456
( scratchpad ) 2 64 ^ dup * .
340282366920938463463374607431768211456

View 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

View 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

View 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))
}

View file

@ -0,0 +1 @@
println 2**64 * 2**64

View 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

View file

@ -0,0 +1,2 @@
*Main> (2^64) `longmult` (2^64)
340282366920938463463374607431768211456

View file

@ -0,0 +1,3 @@
procedure main()
write(2^64*2^64)
end

View file

@ -0,0 +1,5 @@
digits =: ,.&.":
polymult =: +//.@(*/)
buildDecimal=: 10x&#.
longmult=: buildDecimal@polymult&digits

View file

@ -0,0 +1,2 @@
longmult~ 2x^64
340282366920938463463374607431768211456

View file

@ -0,0 +1 @@
longmult=: 10x&#.@(+//.@(*/)&(,.&.":))

View file

@ -0,0 +1,2 @@
10x&#.@(+//.@(*/)&(,.&.":))~2x^64
340282366920938463463374607431768211456

View file

@ -0,0 +1,2 @@
(+ 10x&*)/@|.@(+//.@(*/)&(,.&.":))~2x^64
340282366920938463463374607431768211456

View file

@ -0,0 +1,2 @@
(2x^64)*(2x^64)
340282366920938463463374607431768211456

View file

@ -0,0 +1,2 @@
,.&.": 123
1 2 3

View file

@ -0,0 +1,2 @@
1 2 3 (+//.@(*/)) 1 2 3
1 4 10 12 9

View file

@ -0,0 +1,2 @@
(+ 10x&*)/|. 1 4 10 12 9
15129

View 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);
}
}

View 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("");
}

View file

@ -0,0 +1 @@
print 2^64 *2^64

View file

@ -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]}]
]

View file

@ -0,0 +1,3 @@
n1 = 2^64;
n2 = 2^64;
LongMultiplication[n1, n2]

View file

@ -0,0 +1 @@
340282366920938463463374607431768211456

View file

@ -0,0 +1,5 @@
n1=2^8000;
n2=2^8000;
Timing[LongMultiplication[n1,n2]][[1]]
Timing[n1 n2][[1]]
Floor[%%/%]

View file

@ -0,0 +1,3 @@
72.9686
7.*10^-6
10424088

View file

@ -0,0 +1,6 @@
<?php
$factor = bcpow(2, 64);
$product = bcmul($factor, $factor);
echo "2^64 * 2^64 is " . $product;
?>

View 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";

View file

@ -0,0 +1,2 @@
: (* (** 2 64) (** 2 64))
-> 340282366920938463463374607431768211456

View file

@ -0,0 +1,2 @@
?- X is 2**64 * 2**64.
X = 340282366920938463463374607431768211456.

View file

@ -0,0 +1,2 @@
#!/usr/bin/env python
print 2**64*2**64

View 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)

View 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)

View file

@ -0,0 +1,3 @@
library(gmp)
a <- as.bigz("18446744073709551616")
mul.bigz(a,a)

View 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)

View 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)

View 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)

View 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)))

View 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)))

View file

@ -0,0 +1 @@
(* (expt 2 64) (expt 2 64))

View file

@ -0,0 +1 @@
(2 raisedTo: 64) * (2 raisedTo: 64).

View 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}]