Long multiplication: Difference between revisions
Content added Content deleted
Alextretyak (talk | contribs) (Added 11l) |
|||
Line 5,453: | Line 5,453: | ||
{{out}} |
{{out}} |
||
3402823669293846346337467431768211456 |
3402823669293846346337467431768211456 |
||
The above code does not really integrate into the Smalltalk class library. For example, it will not allow mixed mode arithmetic between regular integers and ''Rosetta integers''. |
|||
Here is a full example in portable chunk file format which makes mixed mode arithmetic completely transparent (I implemented only addition and multiplication): |
|||
<lang smalltalk>Integer |
|||
subclass: #RosettaInteger |
|||
instanceVariableNames:'digitArray' |
|||
classVariableNames:'WORDMAX' |
|||
package:'Rosetta demos' |
|||
! |
|||
!RosettaInteger class methodsFor:'initialization'! |
|||
initialize |
|||
WORDMAX := 100. |
|||
! ! |
|||
!RosettaInteger class methodsFor:'instance creation'! |
|||
newWithDigits:digitArray |
|||
"returns a new RosettaInteger with a digitArray" |
|||
^ self basicNew digits:digitArray |
|||
! |
|||
fromInteger:anInteger |
|||
"returns a new RosettaInteger with anInteger's value" |
|||
|digits gen| |
|||
gen := [:n :s | |
|||
s nextPut:(n % 100). |
|||
n > 99 ifTrue:[ gen value:(n // 100) value:s]]. |
|||
digits := Array streamContents:[:s | gen value:anInteger value:s]. |
|||
^ self newWithDigits:digits |
|||
! ! |
|||
!RosettaInteger class methodsFor:'helpers'! |
|||
addDigits:a and:b |
|||
|add| |
|||
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]. |
|||
]. |
|||
]. |
|||
^ add value:a value:b |
|||
! |
|||
mulDigits:a and:b |
|||
|mulW| |
|||
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]. |
|||
] |
|||
]. |
|||
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 := self addDigits:sum and:shifted. |
|||
]. |
|||
sum. |
|||
]. |
|||
^ mul value:a value:b. |
|||
! ! |
|||
!RosettaInteger methodsFor:'private accessing'! |
|||
digits |
|||
"return my digitArray" |
|||
^ digitArray |
|||
! |
|||
digits:digits |
|||
"set my digitArray" |
|||
digitArray := digits |
|||
! ! |
|||
!RosettaInteger methodsFor:'arithmetic'! |
|||
+ aNumber |
|||
^ aNumber sumFromRosettaInteger:self |
|||
! |
|||
* aNumber |
|||
^ aNumber productFromRosettaInteger:self |
|||
! |
|||
raisedTo:exp |
|||
|raise| |
|||
raise := |
|||
[:a :exp | |
|||
|e rslt| |
|||
rslt := #(1). |
|||
t := a. |
|||
e := exp. |
|||
[e ~~ 0] whileTrue:[ |
|||
[(e bitAnd:1) == 0] whileTrue:[ |
|||
e := e bitShift:-1. |
|||
t := self class mulDigits:t and:t. |
|||
]. |
|||
e := e - 1. |
|||
rslt := self class mulDigits:rslt and:t. |
|||
]. |
|||
rslt. |
|||
]. |
|||
^ self class newWithDigits:(raise value:(self digits) value:exp) |
|||
! |
|||
sumFromRosettaInteger:anRInt |
|||
^ self class |
|||
newWithDigits:(self class addDigits:(anRInt digits) and:(self digits)) |
|||
! |
|||
productFromRosettaInteger:anRInt |
|||
^ self class newWithDigits:(self class mulDigits:(anRInt digits) and:(self digits)) |
|||
! ! |
|||
!RosettaInteger methodsFor:'printing'! |
|||
printOn:aStream |
|||
|print| |
|||
print := |
|||
[:n :stream | |
|||
|first| |
|||
first := true. |
|||
n reverseDo:[:_2Digits | |
|||
first |
|||
ifTrue:[ stream nextPutAll:(_2Digits printString)] |
|||
ifFalse:[ stream nextPutAll:(_2Digits printString leftPaddedTo:2 with:$0)]. |
|||
first := false. |
|||
]. |
|||
]. |
|||
print value:(self digits) value:aStream |
|||
! ! |
|||
!Integer methodsFor:'converting'! |
|||
asRosettaInteger |
|||
^ RosettaInteger fromInteger:self |
|||
! ! |
|||
!Integer methodsFor:'double dispatching'! |
|||
sumFromRosettaInteger:anRInt |
|||
^ anRInt + (RosettaInteger fromInteger:self) |
|||
! |
|||
productFromRosettaInteger:anRInt |
|||
^ anRInt * (RosettaInteger fromInteger:self) |
|||
! ! |
|||
RosettaInteger initialize |
|||
! |
|||
a := 124 asRosettaInteger. |
|||
e'a is: {a} ({a class})' printCR. |
|||
b := 333 asRosettaInteger. |
|||
e'b is: {b} ({b class})'printCR. |
|||
a_plus_b := a+b. |
|||
e'(a+b) is: {a_plus_b} ({(a_plus_b) class})' printCR. |
|||
c := 999 asRosettaInteger. |
|||
e'c is: {c} ({c class})' printCR. |
|||
c_plus_1 := c+1. |
|||
e'c+1 is: {c_plus_1} ({(c_plus_1) class})' printCR. |
|||
d := 100 asRosettaInteger. |
|||
e'd is: {d} ({d class})' printCR. |
|||
d_squared := d squared. |
|||
e'd squared is: {d_squared} ({d_squared class})' printCR. |
|||
e := 2 asRosettaInteger. |
|||
e_raisedTo_64 := e raisedTo:64. |
|||
e'2 raisedTo:64 is: {e_raisedTo_64} ({e_raisedTo_64 class})' printCR. |
|||
e_raisedTo_64_squared := (e raisedTo:64) squared. |
|||
e'result is: {e_raisedTo_64_squared} ({e_raisedTo_64_squared class})' printCR. |
|||
Transcript show:'once again: '. |
|||
result := (2 asRosettaInteger raisedTo:64) squared. |
|||
Transcript showCR:result.</lang> |
|||
{{out}} |
|||
<pre>a is: 124 (RosettaInteger) |
|||
b is: 333 (RosettaInteger) |
|||
(a+b) is: 457 (RosettaInteger) |
|||
c is: 999 (RosettaInteger) |
|||
c+1 is: 1000 (RosettaInteger) |
|||
d is: 100 (RosettaInteger) |
|||
d squared is: 10000 (RosettaInteger) |
|||
2 raisedTo:64 is: 18446744073709551616 (RosettaInteger) |
|||
result is: 340282366920938463463374607431768211456 (RosettaInteger) |
|||
once again: 340282366920938463463374607431768211456</pre> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |