ActionScript3.0 大数据类型
View Code
1 /* *
2 * BigInt
3 * An ActionScript 3 implementation of Big Integer (light version)
4 * Copyright (c) 2009 Alex.li
5 * http://www.cppblog.com/sleepwom/archive/2009/12/14/103180.html
6 * Derived from:
7 * BigInt.js - Arbitrary size integer math package for JavaScript
8 * Copyright (C) 2000 Masanao Izumo <iz@onicos.co.jp>
9 *
10 * Interfaces:
11 * var x:BigInt = new BigInt("1234567890123456789012345678901234567890");
12 * var y:BigInt = new BigInt("0x123456789abcdef0123456789abcdef0");
13 * var z:BigInt = x.clone();
14 * z = x.negative();
15 * z = BigInt.plus(x, y);
16 * z = BigInt.minus(x, y);
17 * z = BigInt.multiply(x, y);
18 * z = BigInt.divide(x, y);
19 * z = BigInt.mod(x, y);
20 * var compare:int = BigInt.compare(x, y); //return -1, 0, or 1
21 * var num:Number = x.toNumber(); //convert to normal number
22 */
23
24 package
25 {
26 public class BigInt
27 {
28 // sign of BigInt, negative or not
29 private var _sign:Boolean;
30 // length of BigInt
31 private var _len: int ;
32 // digits of BigInt
33 private var _digits:Array;
34
35 public function BigInt(arg)
36 {
37 var i: * , x: * , need_init:Boolean;
38
39 if (arg.length == 0 )
40 {
41 _sign = true ;
42 _len = 1 ;
43 _digits = new Array( 1 );
44 need_init = true ;
45 } else if (arg.length == 1 )
46 {
47 x = getBigIntFromAny(arg[ 0 ]);
48 if (x == arg[ 0 ]) x = x.clone();
49 _sign = x._sign;
50 _len = x._len;
51 _digits = x._digits;
52 need_init = false ;
53 } else
54 {
55 _sign = (arg[ 1 ] ? true : false );
56 _len = arg[ 0 ];
57 _digits = new Array(_len);
58 need_init = true ;
59 }
60
61 if (need_init)
62 {
63 for (i = 0 ; i < _len; i ++ )
64 _digits[i] = 0 ;
65 }
66 }
67
68 public function toString():String
69 {
70 return this .toStringBase( 10 );
71 }
72
73 public function toStringBase( base : int ):String
74 {
75 var i: * , j: * , hbase: * ;
76 var t: * ;
77 var ds: * ;
78 var c: * ;
79
80 i = this ._len;
81 if (i == 0 ) return " 0 " ;
82 if (i == 1 && ! this ._digits[ 0 ]) return " 0 " ;
83
84 switch ( base ) {
85 default :
86 case 10 :
87 j = Math.floor(( 2 * 8 * i * 241 ) / 800 ) + 2 ;
88 hbase = 10000 ;
89 break ;
90
91 case 16 :
92 j = Math.floor(( 2 * 8 * i) / 4 ) + 2 ;
93 hbase = 0x10000 ;
94 break ;
95
96 case 8 :
97 j = ( 2 * 8 * i) + 2 ;
98 hbase = 010000 ;
99 break ;
100
101 case 2 :
102 j = ( 2 * 8 * i) + 2 ;
103 hbase = 020 ;
104 break ;
105 }
106
107 t = this .clone();
108 ds = t._digits;
109 var s:String = "" ;
110
111 while (i && j)
112 {
113 var k: * = i;
114 var num: * = 0 ;
115
116 while (k -- )
117 {
118 num = (num << 16 ) + ds[k];
119 if (num < 0 ) num += 4294967296 ;
120 ds[k] = Math.floor(num / hbase);
121 num %= hbase;
122 }
123
124 if (ds[i - 1 ] == 0 )
125 i -- ;
126 k = 4 ;
127 while (k -- )
128 {
129 c = (num % base );
130 s = " 0123456789abcdef " .charAt(c) + s;
131 -- j;
132 num = Math.floor(num / base );
133 if (i == 0 && num == 0 )
134 {
135 break ;
136 }
137 }
138 }
139
140 i = 0 ;
141 while (i < s.length && s.charAt(i) == " 0 " )
142 i ++ ;
143 if (i)
144 s = s.substring(i, s.length);
145 if ( ! this ._sign)
146 s = " - " + s;
147 return s;
148 }
149
150 public function clone():BigInt
151 {
152 var x:BigInt, i: int ;
153
154 x = new BigInt( this ._len, this ._sign);
155 for (i = 0 ; i < this ._len; i ++ )
156 {
157 x._digits[i] = this ._digits[i];
158 }
159 return x;
160 }
161
162 /* *
163 * become a negative BigInt
164 * @return
165 */
166 public function negative():BigInt
167 {
168 var n:BigInt = this .clone();
169 n._sign = ! n._sign;
170 return normalize(n);
171 }
172
173 public function toNumber():Number
174 {
175 var d: * = 0.0 ;
176 var i: * = _len;
177 var ds: * = _digits;
178
179 while (i -- )
180 {
181 d = ds[i] + 65536.0 * d;
182 }
183 if ( ! _sign) d = - d;
184 return d;
185 }
186
187 public function get sign():Boolean
188 {
189 return _sign;
190 }
191
192 public function get length(): int
193 {
194 return _len;
195 }
196
197 public function get digits():Array
198 {
199 return _digits;
200 }
201
202
203 /* ************ public static methods ************* */
204
205
206 public static function plus(x: * , y: * ):BigInt
207 {
208 x = getBigIntFromAny(x);
209 y = getBigIntFromAny(y);
210 return add(x, y, 1 );
211 }
212
213 public static function minus(x: * , y: * ):BigInt
214 {
215 x = getBigIntFromAny(x);
216 y = getBigIntFromAny(y);
217 return add(x, y, 0 );
218 }
219
220 public static function multiply(x: * , y: * ):BigInt
221 {
222 var i: * , j: * ;
223 var n: * = 0 ;
224 var z: * ;
225 var zds: * , xds: * , yds: * ;
226 var dd: * , ee: * ;
227 var ylen: * ;
228
229 x = getBigIntFromAny(x);
230 y = getBigIntFromAny(y);
231
232 j = x._len + y._len + 1 ;
233 z = new BigInt(j, x._sign == y._sign);
234
235 xds = x._digits;
236 yds = y._digits;
237 zds = z._digits;
238 ylen = y._len;
239
240 while (j -- ) zds[j] = 0 ;
241 for (i = 0 ; i < x._len; i ++ )
242 {
243 dd = xds[i];
244 if (dd == 0 ) continue ;
245 n = 0 ;
246 for (j = 0 ; j < ylen; j ++ )
247 {
248 ee = n + dd * yds[j];
249 n = zds[i + j] + ee;
250 if (ee) zds[i + j] = (n & 0xffff );
251 n >>>= 16 ;
252 }
253 if (n)
254 {
255 zds[i + j] = n;
256 }
257 }
258 return normalize(z);
259 }
260
261 public static function divide(x: * , y: * ):BigInt
262 {
263 x = getBigIntFromAny(x);
264 y = getBigIntFromAny(y);
265 return divideAndMod(x, y, 0 );
266 }
267
268 public static function mod(x: * , y: * ):BigInt
269 {
270 x = getBigIntFromAny(x);
271 y = getBigIntFromAny(y);
272 return divideAndMod(x, y, 1 );
273 }
274
275 /* *
276 * compare two BigInts, if x=y return 0, if x>y return 1, if x<y return -1.
277 * @param x
278 * @param y
279 * @return
280 */
281 public static function compare(x: * , y: * ): int
282 {
283 var xlen: * ;
284
285 if (x == y) return 0 ;
286
287 x = getBigIntFromAny(x);
288 y = getBigIntFromAny(y);
289 xlen = x._len;
290
291 if (x._sign != y._sign)
292 {
293 if (x._sign) return 1 ;
294 return - 1 ;
295 }
296
297 if (xlen < y._len) return (x._sign) ? - 1 : 1 ;
298 if (xlen > y._len) return (x._sign) ? 1 : - 1 ;
299
300 while (xlen -- && (x._digits[xlen] == y._digits[xlen]));
301 if ( - 1 == xlen) return 0 ;
302
303 return (x._digits[xlen] > y._digits[xlen]) ?
304 (x._sign ? 1 : - 1 ) :
305 (x._sign ? - 1 : 1 );
306 }
307
308
309 /* ************ private static methods ************* */
310
311
312 private static function getBigIntFromAny(x: * ):BigInt
313 {
314 if ( typeof (x) == " object " )
315 {
316 if (x is BigInt) return x;
317 return new BigInt( 1 , 1 );
318 }
319
320 if ( typeof (x) == " string " )
321 {
322
323 return getBigIntFromString(x);
324 }
325
326 if ( typeof (x) == " number " )
327 {
328 var i: * , x1: * , x2: * , fpt: * , np: * ;
329
330 if ( - 2147483647 <= x && x <= 2147483647 )
331 {
332 return getBigIntFromInt(x);
333 }
334 x = x + "" ;
335 i = x.indexOf( " e " , 0 );
336 if (i == - 1 ) return getBigIntFromString(x);
337 x1 = x.substr( 0 , i);
338 x2 = x.substr(i + 2 , x.length - (i + 2 ));
339
340 fpt = x1.indexOf( " . " , 0 );
341 if (fpt != - 1 )
342 {
343 np = x1.length - (fpt + 1 );
344 x1 = x1.substr( 0 , fpt) + x1.substr(fpt + 1 , np);
345 x2 = parseInt(x2) - np;
346 } else
347 {
348 x2 = parseInt(x2);
349 }
350 while (x2 -- > 0 )
351 {
352 x1 += " 0 " ;
353 }
354 return getBigIntFromString(x1);
355 }
356 return new BigInt( 1 , 1 );
357 }
358
359 private static function getBigIntFromInt(n:Number):BigInt
360 {
361 var sign: * , big:BigInt, i: * ;
362
363 if (n < 0 )
364 {
365 n = - n;
366 sign = false ;
367 } else
368 {
369 sign = true ;
370 }
371 n &= 0x7FFFFFFF ;
372
373 if (n <= 0xFFFF )
374 {
375 big = new BigInt( 1 , 1 );
376 big._digits[ 0 ] = n;
377 } else
378 {
379 big = new BigInt( 2 , 1 );
380 big._digits[ 0 ] = (n & 0xffff );
381 big._digits[ 1 ] = ((n >> 16 ) & 0xffff );
382 }
383 return big;
384 }
385
386 private static function getBigIntFromString(str:String, base : * = null ):BigInt
387 {
388 var str_i: * ;
389 var sign:Boolean = true ;
390 var c: * ;
391 var len: * ;
392 var z: * ;
393 var zds: * ;
394 var num: * ;
395 var i: * ;
396 var blen: * = 1 ;
397
398 str += " @ " ;
399 str_i = 0 ;
400
401 if (str.charAt(str_i) == " + " )
402 {
403 str_i ++ ;
404 } else if (str.charAt(str_i) == " - " )
405 {
406 str_i ++ ;
407 sign = false ;
408 }
409
410 if (str.charAt(str_i) == " @ " )
411 return null ;
412
413 if ( ! base )
414 {
415 if (str.charAt(str_i) == " 0 " )
416 {
417 c = str.charAt(str_i + 1 );
418 if (c == " x " || c == " X " )
419 {
420 base = 16 ;
421 } else if (c == " b " || c == " B " )
422 {
423 base = 2 ;
424 } else
425 {
426 base = 8 ;
427 }
428 } else
429 {
430 base = 10 ;
431 }
432 }
433
434 if ( base == 8 )
435 {
436 while (str.charAt(str_i) == " 0 " )
437 str_i ++ ;
438 len = 3 * (str.length - str_i);
439 } else
440 {
441 if ( base == 16 && str.charAt(str_i) == ' 0 ' && (str.charAt(str_i + 1 ) == " x " || str.charAt(str_i + 1 ) == " X " ))
442 {
443 str_i += 2 ;
444 }
445 if ( base == 2 && str.charAt(str_i) == ' 0 ' && (str.charAt(str_i + 1 ) == " b " || str.charAt(str_i + 1 ) == " B " ))
446 {
447 str_i += 2 ;
448 }
449 while (str.charAt(str_i) == " 0 " )
450 str_i ++ ;
451 if (str.charAt(str_i) == " @ " ) str_i -- ;
452 len = 4 * (str.length - str_i);
453 }
454
455 len = (len >> 4 ) + 1 ;
456 z = new BigInt(len, sign);
457 zds = z._digits;
458
459 while ( true )
460 {
461 c = str.charAt(str_i ++ );
462 if (c == " @ " )
463 break ;
464 switch (c)
465 {
466 case ' 0 ' : c = 0 ; break ;
467 case ' 1 ' : c = 1 ; break ;
468 case ' 2 ' : c = 2 ; break ;
469 case ' 3 ' : c = 3 ; break ;
470 case ' 4 ' : c = 4 ; break ;
471 case ' 5 ' : c = 5 ; break ;
472 case ' 6 ' : c = 6 ; break ;
473 case ' 7 ' : c = 7 ; break ;
474 case ' 8 ' : c = 8 ; break ;
475 case ' 9 ' : c = 9 ; break ;
476 case ' a ' : case ' A ' : c = 10 ; break ;
477 case ' b ' : case ' B ' : c = 11 ; break ;
478 case ' c ' : case ' C ' : c = 12 ; break ;
479 case ' d ' : case ' D ' : c = 13 ; break ;
480 case ' e ' : case ' E ' : c = 14 ; break ;
481 case ' f ' : case ' F ' : c = 15 ; break ;
482 default :
483 c = base ;
484 break ;
485 }
486 if (c >= base ) break ;
487
488 i = 0 ;
489 num = c;
490 while ( true )
491 {
492 while (i < blen)
493 {
494 num += zds[i] * base ;
495 zds[i ++ ] = (num & 0xffff );
496 num >>>= 16 ;
497 }
498 if (num)
499 {
500 blen ++ ;
501 continue ;
502 }
503 break ;
504 }
505 }
506 return normalize(z);
507 }
508
509 private static function add(x:BigInt, y:BigInt, sign: * ):BigInt
510 {
511 var z: * ;
512 var num: * ;
513 var i: * , len: * ;
514
515 sign = (sign == y._sign);
516 if (x._sign != sign)
517 {
518 if (sign) return subtract(y, x);
519 return subtract(x, y);
520 }
521
522 if (x._len > y._len)
523 {
524 len = x._len + 1 ;
525 z = x; x = y; y = z;
526 } else
527 {
528 len = y._len + 1 ;
529 }
530 z = new BigInt(len, sign);
531
532 len = x._len;
533 for (i = 0 , num = 0 ; i < len; i ++ )
534 {
535 num += x._digits[i] + y._digits[i];
536 z._digits[i] = (num & 0xffff );
537 num >>>= 16 ;
538 }
539 len = y._len;
540 while (num && i < len)
541 {
542 num += y._digits[i];
543 z._digits[i ++ ] = (num & 0xffff );
544 num >>>= 16 ;
545 }
546 while (i < len)
547 {
548 z._digits[i] = y._digits[i];
549 i ++ ;
550 }
551 z._digits[i] = (num & 0xffff );
552 return normalize(z);
553 }
554
555 private static function subtract(x:BigInt, y:BigInt):BigInt
556 {
557 var z: * = 0 ;
558 var zds: * ;
559 var num: * ;
560 var i: * ;
561
562 i = x._len;
563 if (x._len < y._len)
564 {
565 z = x; x = y; y = z;
566 } else if (x._len == y._len)
567 {
568 while (i > 0 )
569 {
570 i -- ;
571 if (x._digits[i] > y._digits[i])
572 {
573 break ;
574 }
575 if (x._digits[i] < y._digits[i])
576 {
577 z = x; x = y; y = z;
578 break ;
579 }
580 }
581 }
582
583 z = new BigInt(x._len, (z == 0 ) ? 1 : 0 );
584 zds = z._digits;
585
586 for (i = 0 , num = 0 ; i < y._len; i ++ )
587 {
588 num += x._digits[i] - y._digits[i];
589 zds[i] = (num & 0xffff );
590 num >>>= 16 ;
591 }
592 while (num && i < x._len)
593 {
594 num += x._digits[i];
595 zds[i ++ ] = (num & 0xffff );
596 num >>>= 16 ;
597 }
598 while (i < x._len)
599 {
600 zds[i] = x._digits[i];
601 i ++ ;
602 }
603 return normalize(z);
604 }
605
606 private static function divideAndMod(x:BigInt, y:BigInt, modulo: * ):BigInt
607 {
608 var nx: * = x._len;
609 var ny: * = y._len;
610 var i: * , j: * ;
611 var yy: * , z: * ;
612 var xds: * , yds: * , zds: * , tds: * ;
613 var t2: * ;
614 var num: * ;
615 var dd: * , q: * ;
616 var ee: * ;
617 var mod: * , div: * ;
618
619 yds = y._digits;
620 if (ny == 0 && yds[ 0 ] == 0 ) return null ;
621
622 if (nx < ny || nx == ny && x._digits[nx - 1 ] < y._digits[ny - 1 ])
623 {
624 if (modulo) return normalize(x);
625 return new BigIt( 1 , 1 );
626 }
627
628 xds = x._digits;
629 if (ny == 1 )
630 {
631 dd = yds[ 0 ];
632 z = x.clone();
633 zds = z._digits;
634 t2 = 0 ;
635 i = nx;
636 while (i -- )
637 {
638 t2 = t2 * 65536 + zds[i];
639 zds[i] = (t2 / dd) & 0xffff ;
640 t2 %= dd;
641 }
642 z._sign = (x._sign == y._sign);
643 if (modulo)
644 {
645 if ( ! x._sign) t2 = - t2;
646 if (x._sign != y._sign)
647 {
648 t2 = t2 + yds[ 0 ] * (y._sign ? 1 : - 1 );
649 }
650 return getBigIntFromInt(t2);
651 }
652 return normalize(z);
653 }
654
655 z = new BigInt(nx == ny ? nx + 2 : nx + 1 , x._sign == y._sign);
656 zds = z._digits;
657 if (nx == ny) zds[nx + 1 ] = 0 ;
658 while ( ! yds[ny - 1 ]) ny -- ;
659 if ((dd = (( 65536 / (yds[ny - 1 ] + 1 )) & 0xffff )) != 1 )
660 {
661 yy = y.clone();
662 tds = yy._digits;
663 j = 0 ;
664 num = 0 ;
665 while (j < ny)
666 {
667 num += yds[j] * dd;
668 tds[j ++ ] = num & 0xffff ;
669 num >>= 16 ;
670 }
671 yds = tds;
672 j = 0 ;
673 num = 0 ;
674 while (j < nx)
675 {
676 num += xds[j] * dd;
677 zds[j ++ ] = num & 0xffff ;
678 num >>= 16 ;
679 }
680 zds[j] = num & 0xffff ;
681 } else
682 {
683 zds[nx] = 0 ;
684 j = nx;
685 while (j -- ) zds[j] = xds[j];
686 }
687 j = nx == ny ? nx + 1 : nx;
688
689 do
690 {
691 if (zds[j] == yds[ny - 1 ]) q = 65535 ;
692 else q = ((zds[j] * 65536 + zds[j - 1 ]) / yds[ny - 1 ]) & 0xffff ;
693 if (q)
694 {
695 i = 0 ; num = 0 ; t2 = 0 ;
696 do
697 {
698 t2 += yds[i] * q;
699 ee = num - (t2 & 0xffff );
700 num = zds[j - ny + i] + ee;
701 if (ee) zds[j - ny + i] = num & 0xffff ;
702 num >>= 16 ;
703 t2 >>>= 16 ;
704 } while ( ++ i < ny);
705
706 num += zds[j - ny + i] - t2;
707 while (num)
708 {
709 i = 0 ; num = 0 ; q -- ;
710 do
711 {
712 ee = num + yds[i];
713 num = zds[j - ny + i] + ee;
714 if (ee) zds[j - ny + i] = num & 0xffff ;
715 num >>= 16 ;
716 } while ( ++ i < ny);
717 num -- ;
718 }
719 }
720 zds[j] = q;
721 } while ( -- j >= ny);
722
723 if (modulo)
724 {
725 mod = z.clone();
726 if (dd)
727 {
728 zds = mod._digits;
729 t2 = 0 ; i = ny;
730 while (i -- )
731 {
732 t2 = (t2 * 65536 ) + zds[i];
733 zds[i] = (t2 / dd) & 0xffff ;
734 t2 %= dd;
735 }
736 }
737 mod._len = ny;
738 mod._sign = x._sign;
739 if (x._sign != y._sign)
740 {
741 return add(mod, y, 1 );
742 }
743 return normalize(mod);
744 }
745
746 div = z.clone();
747 zds = div._digits;
748 j = (nx == ny ? nx + 2 : nx + 1 ) - ny;
749 for (i = 0 ; i < j; i ++ ) zds[i] = zds[i + ny];
750 div._len = i;
751 return normalize(div);
752 }
753
754 private static function normalize(x:BigInt):BigInt
755 {
756 var len: * = x._len;
757 var ds: * = x._digits;
758
759 while (len -- && ! ds[len]);
760 x._len = ++ len;
761 return x;
762 }
763 }
764 }
分享给大家看一下。