And they chose one that wasn’t too optimized. There are much better versions of factorial already implemented in Smalltalk:
https://medium.com/concerning-pharo/speeding-up-factorial-computation-by-changing-the-order-of-multiplications-f4da3a5576da http://forum.world.st/Challenge-Tuning-the-large-factorial-td3588660.html Both of these pages have optimizations that eliminate 80% or more of the running time where the optimized version below only eliminates ~25% of the slow factorial’s running time. On my machine, running the factorial for 200,000 takes ~20 seconds using the old/slow algorithm (once I fixed it to be recursive on itself and not the modified factorial method), and the new factorial method takes ~15 seconds. Using the #productTo: method above, takes ~4 seconds, and using my revised version on the other page above takes ~3.5 seconds. My personal preference for a factorial included with Pharo would be the #productTo: method above. It is simple to understand and is reasonably fast. John Brant > On May 16, 2020, at 11:17 AM, Bernhard Höfner <[email protected]> wrote: > > It seems that someone needed an optimized factorial-routine… > The problem on the other hand is, that the machine friendly code is much less > „didactical" than the human friendly common implementation. To have both I > propose to add the human friendly clear and short version as comment. Its a > bit like some primitive methods were after the primitive call there is the > smalltalk version as well (VisualWorks). > > Regards, Bernhard Höfner > >> ... >> The algos are different: >> >> Pharo 8: >> Integer>>factorial >> "Answer the factorial of the receiver." >> >> self = 0 ifTrue: [^ 1]. >> self > 0 ifTrue: [^ self * (self - 1) factorial]. >> self error: 'Not valid for negative integers' >> >> >> Pharo 9: >> >> Integer>>factorial >> | nex nexnext acc | >> "Guard for know cases (0,1,2,error)" >> self < 3 >> ifTrue: [ ^ self < 0 >> ifTrue: [ >> self error: 'Not valid for negative integers' ] >> ifFalse: [ >> self > 0 >> >> ifTrue: [ self ] >> >> ifFalse: [ 1 ] ] ]. >> acc := 2. >> nex := 2. >> nexnext := 10. >> >> self // 2 - 1 >> timesRepeat: [ nex := nex + nexnext. >> nexnext := nexnext + 8. >> acc := acc * nex ]. >> self odd >> ifTrue: [ acc := acc * self ]. >> ^ acc >> >> ...
