Long multiplication: Difference between revisions

(optionally verify against builtin added to task)
Line 5,259:
 
=={{header|Smalltalk}}==
(Note that arbitrary precision arithmetic is native in Smalltalk), and no-one would reinvent the wheel.
<lang smalltalk>(2 raisedTo: 64) * (2 raisedTo: 64).</lang>
or, to display it:
Line 5,267:
{{out}}
340282366920938463463374607431768211456
 
There has been some discussion, if the above is fair...
but then, I guess even using 32bit arithmetic is unfair to 8bit assembly language machines ;-)
 
Anyway, here is a version which works on 2-digit decimal machine of the 1940's...
 
<lang Smalltalk>"/ mhmh hard to avoid largeInteger arithmetic,
"/ as the language does not specify, how many bits are used to represent
"/ SmallIntegers, and when the VM uses LargeInts.
"/ Lets assume, we run on a 16 bit machine (smile).
"/ So lets work hard to avoid any convenient VM support,
"/ by doing decimal arithmetic (running on a decimal machine from the 1940's)
"/ and only allow 0..99 in a word.
"/ (smile: remember Knuth's MIX machine?)
 
"/ the code below should never ever been taken serious
"/ Not even as didactic example.
"/ NOONE WOULD EVER DO SUCH A STUPID THING
 
WORDMAX := 100.
add :=
[:a :b |
Array streamContents:[:s |
|cy|
cy := 0.
1 to:(a size max:b size) do:[:wordIndex |
|sum|
wA := a at:wordIndex ifAbsent:0.
wB := b at:wordIndex ifAbsent:0.
sum := (wA + wB + cy).
cy := (sum // WORDMAX).
s nextPut:(sum % WORDMAX).
].
cy ~~ 0 ifTrue:[s nextPut:cy].
].
].
 
"/ test 12,34 + 1
a := #( 34 12 ).
b := #( 1 ).
self assert:( add value:a value:b ) = #( 35 12 ).
 
"/ test 99,99 + 1
a := #( 99 99 ).
b := #( 1 ).
self assert:( add value:a value:b ) = #( 00 00 1 ).
 
"/ test 99,99,99,99 + 99,99,99,99
a := #( 99 99 99 99 ).
b := #( 99 99 99 99 ).
self assert:( add value:a value:b ) = #( 98 99 99 99 1).
 
mulW :=
[:a :w |
|cy|
cy := 0.
Array streamContents:[:s |
a do:[:wordA |
|product|
product := (wordA * w) + cy.
s nextPut:(product % WORDMAX).
cy := (product // WORDMAX)
].
cy ~~ 0 ifTrue:[s nextPut:cy].
]
].
 
"/ test 1 * 2
a := #( 1 ).
self assert:( mulW value:a value:2) = #( 2).
 
"/ test 2 * 99
a := #( 2 ).
self assert:( mulW value:a value:99) = #( 98 1).
 
"/ test 99,99,99,99 * 99
a := #( 99 99 99 99 ).
self assert:( mulW value:a value:99) = #( 01 99 99 99 98 ).
 
mul :=
[:a :b |
|sum|
 
sum := #( 0 ).
b doWithIndex:[:wordB :wordIndex |
partSum := mulW value:a value:wordB.
shifted := (Array new:wordIndex-1 withAll:0),partSum.
sum := add value:sum value:shifted.
].
sum.
].
 
"/ test 99,99,99,99 * 99
a := #( 99 99 99 99 ).
b := #( 99 ).
self assert:( mul value:a value:b) = #( 01 99 99 99 98 ).
 
raise :=
[:a :exp |
|e rslt|
 
rslt := #(1).
t := a.
e := exp.
[e ~~ 0] whileTrue:[
[(e bitAnd:1) == 0] whileTrue:[
e := e bitShift:-1.
t := mul value:t value:t.
].
e := e - 1.
rslt := mul value:rslt value:t.
].
rslt.
].
 
"/ test 2 ** 64
a := #( 2 ).
self assert:( raise value:a value:64) = #( 16 16 55 09 37 07 44 67 44 18).
 
"/ test (2 ** 64) * (2 ** 64)
a := #( 2 ).
t := raise value:a value:64.
rslt := mul value:t value:t.
self assert:rslt = #( 56 14 21 68 17 43 07 46 37 63 34 46 38 09 92 66 23 28 40 3).
 
printOn :=
[:n :stream |
|first|
first := true.
n reverseDo:[:_2Digits |
first
ifTrue:[ stream nextPut:_2Digits]
ifFalse:[ stream nextPut:(_2Digits leftPaddedTo:2 with:$0)].
].
].
 
printOn value:rslt value:Transcript.</lang>
{{out}}
3402823669293846346337467431768211456
 
=={{header|Tcl}}==
Anonymous user