2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -1,8 +1,15 @@
In this task, explicitly implement [[wp:long multiplication|long multiplication]]. This is one possible approach to arbitrary-precision integer algebra.
;Task:
Explicitly implement   [[wp:long multiplication|long multiplication]].
[[Category:Arbitrary precision]] [[Category:Arithmetic operations]]
This is one possible approach to arbitrary-precision integer algebra.
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
For output, display the result of &nbsp; <big><big> 2<sup>64</sup> * 2<sup>64</sup>.</big></big>
The decimal representation of &nbsp; <big><big> 2<sup>64</sup> </big></big> &nbsp; is:
18,446,744,073,709,551,616
The output of &nbsp; <big><big> 2<sup>64</sup> * 2<sup>64</sup> </big></big> &nbsp; is &nbsp; <big><big> 2<sup>128</sup>, </big></big> &nbsp; and is:
340,282,366,920,938,463,463,374,607,431,768,211,456
<br><br>

View file

@ -1,2 +1,5 @@
---
category:
- Arbitrary precision
- Arithmetic operations
note: Arbitrary precision

View file

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

View file

@ -0,0 +1,22 @@
function mult(strNum1,strNum2){
var a1 = strNum1.split("").reverse();
var a2 = strNum2.toString().split("").reverse();
var aResult = new Array;
for ( var iterNum1 = 0; iterNum1 < a1.length; iterNum1++ ) {
for ( var iterNum2 = 0; iterNum2 < a2.length; iterNum2++ ) {
var 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("");
}
mult('18446744073709551616', '18446744073709551616')

View file

@ -0,0 +1,98 @@
(function () {
'use strict';
// Javascript lacks an unbounded integer type
// so this multiplication function takes and returns
// long integer strings rather than any kind of native integer
// longMult :: (String | Integer) -> (String | Integer) -> String
function longMult(num1, num2) {
return largeIntegerString(
digitProducts(digits(num1), digits(num2))
);
}
// digitProducts :: [Int] -> [Int] -> [Int]
function digitProducts(xs, ys) {
return multTable(xs, ys)
.map(function (zs, i) {
return Array.apply(null, Array(i))
.map(function () {
return 0;
})
.concat(zs);
})
.reduce(function (a, x) {
if (a) {
var lng = a.length;
return x.map(function (y, i) {
return y + (i < lng ? a[i] : 0);
})
} else return x;
})
}
// largeIntegerString :: [Int] -> String
function largeIntegerString(lstColumnValues) {
var dctProduct = lstColumnValues
.reduceRight(function (a, x) {
var intSum = x + a.carried,
intDigit = intSum % 10;
return {
digits: intDigit
.toString() + a.digits,
carried: (intSum - intDigit) / 10
};
}, {
digits: '',
carried: 0
});
return (dctProduct.carried > 0 ? (
dctProduct.carried.toString()
) : '') + dctProduct.digits;
}
// multTables :: [Int] -> [Int] -> [[Int]]
function multTable(xs, ys) {
return ys.map(function (y) {
return xs.map(function (x) {
return x * y;
})
});
}
// digits :: (Integer | String) -> [Integer]
function digits(n) {
return (typeof n === 'string' ? n : n.toString())
.split('')
.map(function (x) {
return parseInt(x, 10);
});
}
// TEST showing that larged bounded integer inputs give only rounded results
// whereas integer string inputs allow for full precision on this scale (2^128)
return {
fromIntegerStrings: longMult(
'18446744073709551616',
'18446744073709551616'
),
fromBoundedIntegers: longMult(
18446744073709551616,
18446744073709551616
)
};
})();

View file

@ -1,18 +0,0 @@
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,36 @@
fun String.toDigits() = mapIndexed { i, c ->
if (!c.isDigit())
throw IllegalArgumentException("Invalid digit $c found at position $i")
c - '0'
}.reversed()
operator fun String.times(n: String): String {
val left = toDigits()
val right = n.toDigits()
val result = IntArray(left.size + right.size)
right.mapIndexed { rightPos, rightDigit ->
var tmp = 0
left.indices.forEach { leftPos ->
tmp += result[leftPos + rightPos] + rightDigit * left[leftPos]
result[leftPos + rightPos] = tmp % 10
tmp /= 10
}
var destPos = rightPos + left.size
while (tmp != 0) {
tmp += (result[destPos].toLong() and 0xFFFFFFFFL).toInt()
result[destPos] = tmp % 10
tmp /= 10
destPos++
}
}
return result.foldRight(StringBuilder(result.size), { digit, sb ->
if (digit != 0 || sb.length > 0) sb.append('0' + digit)
sb
}).toString()
}
fun main(args: Array<out String>) {
println("18446744073709551616" * "18446744073709551616")
}

View file

@ -1,27 +1,25 @@
/*REXX program performs long multiplication on two numbers (without the "E").*/
numeric digits 3000 /*be able to handle gihugeic input #s. */
parse arg x y . /*obtain the optional one or two #s. */
if x=='' then x=2**64 /*Not specified? Then use the default.*/
if y=='' then y=x /* " " " " " " */
if x<0 && y<0 then sign='-' /*there only a single negative number? */
else sign= /*no, then result sign must be positive*/
xx=x; x=strip(x, 'T', .) /*remove any trailing decimal points. */
yy=y; y=strip(y, 'T', .) /* " " " " ". */
_=left(x,1); if _=='-' | _=='+' then x=substr(x,2) /*elide leading ± signs*/
_=left(y,1); if _=='-' | _=='+' then y=substr(y,2) /* " " " " */
dp=0; Lx=length(x); Ly=length(y) /*get the lengths of the new X and Y. */
f=pos(., x); if f\==0 then dp= Lx-f /*calculate size of decimal fraction. */
f=pos(., y); if f\==0 then dp=dp+Ly-f /* " " " " " */
x=space(translate(x, , .), 0) /*remove decimal point if there is any.*/
y=space(translate(y, , .), 0) /* " " " " " " " */
Lx=length(x); Ly=length(y) /*get the lengths of the new X and Y. */
numeric digits max(digits(), Lx+Ly) /*use a new decimal digits precision.*/
$=0 /*P: is the product (so far). */
do j=Ly by -1 for Ly /*almost like REXX does it, ··· but no.*/
$=$ + ((x*substr(y, j, 1))copies(0, Ly-j) )
end /*j*/
f=length($)-dp /*does product has enough decimal digs?*/
if f<0 then $=copies(0, abs(f)+1)$ /*Negative? Add leading 0s for INSERT.*/
say ' builtin:' xx '*' yy '' xx*yy
say 'long mult:' xx '*' yy '' sign||strip(insert(.,$,length($)-dp),'T',.)
/*stick a fork in it, we're all done. */
/*REXX program performs long multiplication on two numbers (without the "E"). */
numeric digits 300 /*be able to handle gihugeic input #s. */
parse arg x y . /*obtain optional arguments from the CL*/
if x=='' | x=="," then x=2**64 /*Not specified? Then use the default.*/
if y=='' | y=="," then y=x /* " " " " " " */
if x<0 && y<0 then sign= '-' /*there only a single negative number? */
else sign= /*no, then result sign must be positive*/
xx=x; x=strip(x, 'T', .); x1=left(x, 1) /*remove any trailing decimal points. */
yy=y; y=strip(y, 'T', .); y1=left(y, 1) /* " " " " " */
if x1=='-' | x1=="+" then x=substr(x, 2) /*remove a leading ± sign. */
if y1=='-' | y1=="+" then y=substr(y, 2) /* " " " " " */
parse var x '.' xf; parse var y "." yf /*obtain the fractional part of X and Y*/
#=length(xf || yf) /*#: digits past the decimal points (.)*/
x=space( translate( x, , .), 0) /*remove decimal point if there is any.*/
y=space( translate( y, , .), 0) /* " " " " " " " */
Lx=length(x); Ly=length(y) /*get the lengths of the new X and Y. */
numeric digits max(digits(), Lx + Ly) /*use a new decimal digits precision.*/
$=0 /*$: is the product (so far). */
do j=Ly by -1 for Ly /*almost like REXX does it, ··· but no.*/
$=$ + ((x*substr(y, j, 1))copies(0, Ly-j) )
end /*j*/
f=length($) - # /*does product has enough decimal digs?*/
if f<0 then $=copies(0, abs(f) + 1)$ /*Negative? Add leading 0s for INSERT.*/
say 'long mult:' xx "*" yy '' sign || strip( insert(., $, length($) - #), 'T', .)
say ' builtin:' xx "*" yy '' xx*yy /*stick a fork in it, we're all done. */