2016 Update
This commit is contained in:
parent
948b86eafa
commit
dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions
|
|
@ -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 <big><big> 2<sup>64</sup> * 2<sup>64</sup>.</big></big>
|
||||
|
||||
|
||||
The decimal representation of <big><big> 2<sup>64</sup> </big></big> is:
|
||||
18,446,744,073,709,551,616
|
||||
|
||||
The output of <big><big> 2<sup>64</sup> * 2<sup>64</sup> </big></big> is <big><big> 2<sup>128</sup>, </big></big> and is:
|
||||
340,282,366,920,938,463,463,374,607,431,768,211,456
|
||||
<br><br>
|
||||
|
|
|
|||
|
|
@ -1,2 +1,5 @@
|
|||
---
|
||||
category:
|
||||
- Arbitrary precision
|
||||
- Arithmetic operations
|
||||
note: Arbitrary precision
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
procedure main()
|
||||
write(2^64*2^64)
|
||||
write(2^64*2^64)
|
||||
end
|
||||
|
|
|
|||
22
Task/Long-multiplication/JavaScript/long-multiplication-1.js
Normal file
22
Task/Long-multiplication/JavaScript/long-multiplication-1.js
Normal 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')
|
||||
98
Task/Long-multiplication/JavaScript/long-multiplication-2.js
Normal file
98
Task/Long-multiplication/JavaScript/long-multiplication-2.js
Normal 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
|
||||
)
|
||||
};
|
||||
|
||||
})();
|
||||
|
|
@ -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("");
|
||||
}
|
||||
36
Task/Long-multiplication/Kotlin/long-multiplication.kotlin
Normal file
36
Task/Long-multiplication/Kotlin/long-multiplication.kotlin
Normal 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")
|
||||
}
|
||||
|
|
@ -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 ' built─in:' 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 ' built─in:' xx "*" yy '──►' xx*yy /*stick a fork in it, we're all done. */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue