3047 receiver:self |
3046 receiver:self |
3048 selector:#factorial |
3047 selector:#factorial |
3049 arguments:#() |
3048 arguments:#() |
3050 errorString:'factorial of negative number' |
3049 errorString:'factorial of negative number' |
3051 ]. |
3050 ]. |
3052 ^ 1 |
3051 ^ #(1 1 2 6 24 120 720 5040 40320 362880 3628800 39916800 |
3053 ]. |
3052 479001600 6227020800 87178291200 1307674368000 20922789888000 |
|
3053 355687428096000 6402373705728000 121645100408832000 |
|
3054 2432902008176640000) at:self+1 |
|
3055 ]. |
|
3056 |
|
3057 "/ self < 80000 ifTrue:[ |
|
3058 "/ ^ self factorialHalf |
|
3059 "/ ]. |
|
3060 ^ self factorialEvenOdd |
|
3061 |
|
3062 " |
|
3063 10 factorial |
|
3064 100 factorial |
|
3065 1000 factorial |
|
3066 10000 factorial |
|
3067 100000 factorial |
|
3068 200000 factorial |
|
3069 300000 factorial |
|
3070 1000000 factorial |
|
3071 |
|
3072 Time millisecondsToRun:[10000 factorial]40 |
|
3073 Time millisecondsToRun:[100000 factorial]3220 |
|
3074 Time millisecondsToRun:[1000000 factorial]357120 |
|
3075 |
|
3076 #(factorialIter factorialHalf factorialEvenOdd factorial) |
|
3077 do:[:sel | |
|
3078 #( (10000 10) |
|
3079 (20000 10) |
|
3080 (50000 10) |
|
3081 (70000 10) |
|
3082 (100000 5) |
|
3083 (200000 3) |
|
3084 (300000 3) |
|
3085 (400000 3)) pairsDo:[:n :repeat | |
|
3086 |times| |
|
3087 times := (1 to:repeat) collect:[:i | |
|
3088 Time millisecondsToRun:[ n perform:sel] |
|
3089 ]. |
|
3090 |
|
3091 Transcript printf:'%12s %6d: %5d\n' with:sel with:n with:times min |
|
3092 ] |
|
3093 ]. |
|
3094 |
|
3095 factorialIter 10000: 30 |
|
3096 factorialIter 20000: 130 |
|
3097 factorialIter 50000: 790 |
|
3098 factorialIter 70000: 1710 |
|
3099 factorialIter 100000: 4880 |
|
3100 factorialIter 200000: 24980 |
|
3101 factorialIter 300000: 60060 |
|
3102 factorialIter 400000: 112310 |
|
3103 factorialHalf 10000: 20 |
|
3104 factorialHalf 20000: 100 |
|
3105 factorialHalf 50000: 690 |
|
3106 factorialHalf 70000: 1430 |
|
3107 factorialHalf 100000: 3220 |
|
3108 factorialHalf 200000: 28340 |
|
3109 factorialHalf 300000: 68740 |
|
3110 factorialHalf 400000: 127490 |
|
3111 factorialEvenOdd 10000: 10 |
|
3112 factorialEvenOdd 20000: 60 |
|
3113 factorialEvenOdd 50000: 390 |
|
3114 factorialEvenOdd 70000: 810 |
|
3115 factorialEvenOdd 100000: 2020 |
|
3116 factorialEvenOdd 200000: 9960 |
|
3117 factorialEvenOdd 300000: 24480 |
|
3118 factorialEvenOdd 400000: 45340 |
|
3119 factorial 10000: 20 |
|
3120 factorial 20000: 100 |
|
3121 factorial 50000: 680 |
|
3122 factorial 70000: 1400 |
|
3123 factorial 100000: 2040 |
|
3124 factorial 200000: 10130 |
|
3125 factorial 300000: 24670 |
|
3126 " |
|
3127 ! |
|
3128 |
|
3129 factorialEvenOdd |
|
3130 "an recursive odd-even algorithm, which processes smaller largeInts in the loop." |
|
3131 |
|
3132 |pO i s2 t stop| |
|
3133 |
|
3134 (self <= 20) ifTrue:[ |
|
3135 ^ #(1 1 2 6 24 120 720 5040 40320 362880 3628800 39916800 |
|
3136 479001600 6227020800 87178291200 1307674368000 20922789888000 |
|
3137 355687428096000 6402373705728000 121645100408832000 |
|
3138 2432902008176640000) at:self+1 |
|
3139 ]. |
|
3140 |
|
3141 "/ |
|
3142 "/ 3 * 4 * 5 * 6 *7 * 8 .... * n |
|
3143 "/ odd numbers: |
|
3144 "/ 3 5 7 9 ... n |
|
3145 "/ half even: |
|
3146 "/ 2 4 6 8 ... n |
|
3147 "/ 1 2 3 4 ... n//2 |
|
3148 "/ is (n/2)!! << n-1 |
|
3149 |
|
3150 pO := 1. |
|
3151 i := 3. |
|
3152 |
|
3153 "/ odds only in pairs as |
|
3154 "/ i * (i + 2) |
|
3155 "/ to get to the next pair, |
|
3156 "/ (i+4)(i+6) |
|
3157 "/ we add: 8i + 24 |
|
3158 "/ (i+4)(i+6)-(i*(i+2)) |
|
3159 "/ i^2 + 10i + 24 - i^2 - 2i |
|
3160 "/ 8i + 24 |
|
3161 stop := self-2. |
|
3162 t := i*(i+2). |
|
3163 [i <= stop] whileTrue:[ |
|
3164 "/ odd*next odd |
|
3165 pO := pO * t. |
|
3166 t := t + ((i*8) + 24). |
|
3167 i := i + 4. |
|
3168 ]. |
|
3169 |
|
3170 [i <= self] whileTrue:[ |
|
3171 "/ odd |
|
3172 pO := pO * i. |
|
3173 i := i + 2. |
|
3174 ]. |
|
3175 |
|
3176 "/ the factorial of the evens... |
|
3177 s2 := (self//2). |
|
3178 ^ (s2 factorialEvenOdd * pO) << s2. |
|
3179 |
|
3180 " |
|
3181 (6 to:2000) conform:[:i | i factorialIter = i factorialEvenOdd] |
|
3182 |
|
3183 Time millisecondsToRun:[20000 factorialIter] |
|
3184 Time millisecondsToRun:[50000 factorialIter] |
|
3185 Time millisecondsToRun:[70000 factorialIter] |
|
3186 Time millisecondsToRun:[100000 factorialIter] |
|
3187 Time millisecondsToRun:[200000 factorialIter] |
|
3188 |
|
3189 Time millisecondsToRun:[20000 factorialEvenOdd] |
|
3190 Time millisecondsToRun:[50000 factorialEvenOdd] |
|
3191 Time millisecondsToRun:[70000 factorialEvenOdd] |
|
3192 Time millisecondsToRun:[100000 factorialEvenOdd] |
|
3193 Time millisecondsToRun:[200000 factorialEvenOdd] |
|
3194 " |
|
3195 ! |
|
3196 |
|
3197 factorialHalf |
|
3198 "an algorithm, which processes does it with half the number of multiplications. |
|
3199 this is faster than factorialPM to roughly 60000." |
|
3200 |
|
3201 |p i d| |
|
3202 |
|
3203 i := self. |
|
3204 self odd ifTrue:[ |
|
3205 i := i - 1. |
|
3206 ]. |
|
3207 |
|
3208 p := i. |
|
3209 d := i - 2. |
|
3210 [d >= 2] whileTrue:[ |
|
3211 i := i + d. |
|
3212 p := p * i. |
|
3213 d := d - 2. |
|
3214 ]. |
|
3215 self odd ifTrue:[ |
|
3216 p := p * self |
|
3217 ]. |
|
3218 ^ p |
|
3219 |
|
3220 " |
|
3221 10 factorial 3628800 |
|
3222 10 factorialHalf 3628800 |
|
3223 |
|
3224 11 factorial 39916800 |
|
3225 11 factorialHalf 39916800 |
|
3226 |
|
3227 12 factorial 479001600 |
|
3228 12 factorialHalf 479001600 |
|
3229 |
|
3230 10000 factorial = 10000 factorialHalf |
|
3231 |
|
3232 (6 to:2000) conform:[:i | i factorialIter = i factorialHalf] |
|
3233 |
|
3234 Time microsecondsToRun:[30 factorialIter] |
|
3235 Time microsecondsToRun:[30 factorialHalf] |
|
3236 Time microsecondsToRun:[50 factorialIter] |
|
3237 Time microsecondsToRun:[50 factorialHalf] |
|
3238 Time microsecondsToRun:[75 factorialIter] |
|
3239 Time microsecondsToRun:[75 factorialHalf] |
|
3240 Time microsecondsToRun:[100 factorialIter] |
|
3241 Time microsecondsToRun:[100 factorialHalf] |
|
3242 Time microsecondsToRun:[500 factorialIter] |
|
3243 Time microsecondsToRun:[500 factorialHalf] |
|
3244 Time microsecondsToRun:[1000 factorialIter] |
|
3245 Time microsecondsToRun:[1000 factorialHalf] |
|
3246 Time microsecondsToRun:[2000 factorialIter] |
|
3247 Time microsecondsToRun:[2000 factorialHalf] |
|
3248 |
|
3249 Time microsecondsToRun:[500 factorial]118 120 120 |
|
3250 Time microsecondsToRun:[1000 factorial]339 355 406 |
|
3251 Time microsecondsToRun:[5000 factorial]15703 13669 7715 |
|
3252 Time millisecondsToRun:[10000 factorial]40 30 50 |
|
3253 Time millisecondsToRun:[20000 factorial]140 150 150 |
|
3254 Time millisecondsToRun:[40000 factorial]600 570 560 570 |
|
3255 Time millisecondsToRun:[60000 factorial]1220 1240 1340 |
|
3256 Time millisecondsToRun:[80000 factorial]2600 2580 2540 |
|
3257 Time millisecondsToRun:[100000 factorial]4680 4810 5280 |
|
3258 Time millisecondsToRun:[120000 factorial]8100 8010 7920 |
|
3259 Time millisecondsToRun:[150000 factorial]13830 14040 13360 |
|
3260 Time millisecondsToRun:[200000 factorial]23880 23740 |
|
3261 |
|
3262 Time microsecondsToRun:[500 factorialHalf]150 142 192 |
|
3263 Time microsecondsToRun:[1000 factorialHalf]383 527 684 |
|
3264 Time microsecondsToRun:[5000 factorialHalf]6654 9221 4629 |
|
3265 Time millisecondsToRun:[10000 factorialHalf]20 30 20 |
|
3266 Time millisecondsToRun:[20000 factorialHalf]110 110 110 |
|
3267 Time millisecondsToRun:[40000 factorialHalf]490 490 490 |
|
3268 Time millisecondsToRun:[60000 factorialHalf]1100 1090 1070 |
|
3269 Time millisecondsToRun:[80000 factorialHalf]1920 1920 1880 |
|
3270 Time millisecondsToRun:[100000 factorialHalf]3030 3010 3000 |
|
3271 Time millisecondsToRun:[120000 factorialHalf]4830 4770 4760 |
|
3272 Time millisecondsToRun:[150000 factorialHalf]14510 13940 13900 |
|
3273 Time millisecondsToRun:[200000 factorialHalf]28730 28160 |
|
3274 " |
|
3275 ! |
|
3276 |
|
3277 factorialIter |
|
3278 "return fac(self) (i.e. 1*2*3...*self) using an iterative algorithm. |
|
3279 This is slightly faster than the recursive algorithm, and does not |
|
3280 suffer from stack overflow problems (with big receivers)" |
|
3281 |
|
3282 |p i| |
|
3283 |
3054 p := 2. |
3284 p := 2. |
3055 i := 3. |
3285 i := 3. |
3056 [i <= self] whileTrue:[ |
3286 [i <= self] whileTrue:[ |
3057 p := p * i. |
3287 p := p * i. |
3058 i := i + 1. |
3288 i := i + 1. |