玩具程序:bigInt

#0 为什么称作玩具程序?
1、实现简单,也就是效率一般。
2、只具备无符号数的加、乘运算功能。
 
#1 如何实现
以1792为例,用数组0号元素存储2,1号元素存储9,依此类推...
下面是大整数的存储结构图。

存储结构定义:

1 #define MAXDIGITS 64
2 
3 typedef struct {
4     int lastdigit;
5     char digits[MAXDIGITS];
6 } bigNum;

加法实现:按位相加,再加上进位carry。两个数长度未必相同,所以高位的处理需要特别对待。
乘法实现:乘法其实是用加法来实现的,下面列出了伪码实现。

 1 int multiplyBigNum(bigNum * src, bigNum * dst){
 2     bigNum result;
 3     bigNum t;
 4 
 5     for each digit x in dst{
 6         some bookkeeping;
 7         multiplyDigit(src, x, &t);
 8         addBigNum(&result, &t);
 9     }
10 
11     copyBigNum(&result, src);
12 
13     return 0;
14 }

#2 除了初始化bigInt外没有 除法、求余 运算:我构造了查找表,但这也使得程序代码变得更长了。
查找表的构造过程:写几行输出代码,控制台输入输出重定向,拷贝粘帖。如果是手工的话,很可能会出错。

 1     unsigned char cacheMgr[96][2]={
 2         00,    01,    02,    03,    04,   
 3         05,    06,    07,    08,    09,   
 4         10,    11,    12,    13,    14,   
 5         15,    16,    17,    18,    19,   
 6         20,    21,    22,    23,    24,   
 7         25,    26,    27,    28,    29,   
 8         30,    31,    32,    33,    34,   
 9         35,    36,    37,    38,    39,   
10         40,    41,    42,    43,    44,   
11         45,    46,    47,    48,    49,   
12         50,    51,    52,    53,    54,   
13         55,    56,    57,    58,    59,   
14         60,    61,    62,    63,    64,   
15         65,    66,    67,    68,    69,   
16         70,    71,    72,    73,    74,   
17         75,    76,    77,    78,    79,   
18         80,    81,    82,    83,    84,   
19         85,    86,    87,    88,    89,   
20         90,    91,    92,    93,    94,   
21         95
22     };

#3 阶乘运算31!,改下参数运算256!也行的, 运行时间也会长些

 1 int main(){
 2     bigNum src;
 3     bigNum dst;
 4     
 5     makeBigNum(1, &src);
 6     
 7     for (int i=1; i<32; i++){
 8         makeBigNum(i, &dst);
 9         multiplyBigNum(&src, &dst);
10         printfBigNum(&src);
11     }
12 
13     getchar();
14     return 0;
15 }

#4 更多参考

显然,高精度数值运算程序库的编写可以称得上相当professional的工作!如果你想动手,最好找些帮手。【1】有递归实现。【2】有四则运算的完整实现。【3】有齐全的综述。【4】没看过,但显然里面会有权威的描述,必然会有的,哈哈。
【1】Eric S. Roberts. Programming Abstractions in C: A Second Course in Computer Science. Addison-Wesley Educational Publishers Inc.
【2】Steven S. Skiena Miguel A. Revilla. Programming Challenges. Springer Verlag. Ch5.2 High-Precision Integers.
【3】Steven S. Skiena. The Algorithm Design Manual, Second Edition. Springer-Verlag. Ch13.9 Arbitrary-Precision Arithmetic.
【4】D. Knuth. The Art of Computer Programming, Volume 2: Seminumerical Algorithms. Addison-Wesley, Reading MA, third edition, 1997.

#5 代码参考,拍砖请轻点下手

  1 #include <stdio.h>
  2 #include "bigInt.h"
  3 #define MAXDIGITS 64
  4 
  5 typedef struct {
  6     int lastdigit;
  7     char digits[MAXDIGITS];
  8 } bigNum;
  9 
 10 int makeBigNum(int src, bigNum * bn){
 11     bn->lastdigit = -1;
 12     while (src != 0){
 13         bn->lastdigit ++;
 14         bn->digits[bn->lastdigit] = src % 10;
 15         src = src / 10;
 16     }
 17 
 18     return 0;
 19 }
 20 
 21 int printfBigNum(bigNum * bn){
 22     for(int i=bn->lastdigit; i>=0; i--){
 23         printf("%u", bn->digits[i]);
 24         if (i%3 == 0) printf(" ");
 25     }
 26 
 27     printf("\n");
 28 
 29     return 0;
 30 }
 31 
 32 int addBigNum(bigNum * src, bigNum * dst){
 33     unsigned char cacheMgr[20][2]={
 34         00,    01,    02,    03,    04,   
 35         05,    06,    07,    08,    09,   
 36          10,    11,    12,    13,    14,   
 37          15,    16,    17,    18,    19
 38     };
 39     
 40     bigNum * longNum = src;
 41     int shortLength = dst->lastdigit;
 42     if(dst->lastdigit > src->lastdigit){
 43         longNum = dst;
 44         shortLength = src->lastdigit;
 45     }
 46     int length = longNum->lastdigit;
 47 
 48     int carry = 0;
 49     for (int i=0; i<=shortLength; i++){
 50         unsigned char t = src->digits[i] + dst->digits[i] + carry;
 51         src->digits[i] = cacheMgr[t][1];
 52         carry = cacheMgr[t][0];
 53     }
 54 
 55     for (int i=shortLength+1; i<=length; i++){
 56         unsigned char t = longNum->digits[i] + carry;
 57         src->digits[i] = cacheMgr[t][1];
 58         carry = cacheMgr[t][0];
 59     }
 60 
 61     if (carry == 1){
 62         src->lastdigit = longNum->lastdigit+1;
 63         src->digits[src->lastdigit] = 1;
 64     }
 65     else src->lastdigit = longNum->lastdigit;
 66 
 67     return 0;
 68 }
 69 
 70 // src =====> dst
 71 int copyBigNum(bigNum * src, bigNum * dst){
 72     int length = src->lastdigit;
 73     
 74     dst->lastdigit = length;
 75 
 76     for(int i=0; i<=length; i++)
 77         dst->digits[i] = src->digits[i];
 78 
 79     return 0;
 80 }
 81 
 82 int multiplyDigit(bigNum * src, unsigned char digit, bigNum * t){
 83     unsigned char cacheMgr[96][2]={
 84         00,    01,    02,    03,    04,   
 85         05,    06,    07,    08,    09,   
 86         10,    11,    12,    13,    14,   
 87         15,    16,    17,    18,    19,   
 88         20,    21,    22,    23,    24,   
 89         25,    26,    27,    28,    29,   
 90         30,    31,    32,    33,    34,   
 91         35,    36,    37,    38,    39,   
 92         40,    41,    42,    43,    44,   
 93         45,    46,    47,    48,    49,   
 94         50,    51,    52,    53,    54,   
 95         55,    56,    57,    58,    59,   
 96         60,    61,    62,    63,    64,   
 97         65,    66,    67,    68,    69,   
 98         70,    71,    72,    73,    74,   
 99         75,    76,    77,    78,    79,   
100         80,    81,    82,    83,    84,   
101         85,    86,    87,    88,    89,   
102         90,    91,    92,    93,    94,   
103         95
104     };
105 
106     int carry = 0;
107     int length = src->lastdigit;
108     int x;
109 
110     for(int i=0; i<=length; i++){
111         x = src->digits[i] * digit + carry;
112         t->lastdigit++;
113         t->digits[t->lastdigit] = cacheMgr[x][1];
114         carry = cacheMgr[x][0];
115     }
116 
117     if (carry > 0){
118         t->lastdigit = t->lastdigit+1;
119         t->digits[t->lastdigit] = carry;
120     }
121 
122     return 0;
123 }
124 
125 int multiplyBigNum(bigNum * src, bigNum * dst){
126     bigNum result;
127     bigNum t;
128 
129     makeBigNum(0, &result);
130 
131     int length = dst->lastdigit;
132     for (int i=0; i<=length; i++){
133         t.lastdigit = i-1;
134         for (int s=1; s<=i; s++)
135             t.digits[s-1] = 0;
136         multiplyDigit(src, dst->digits[i], &t);
137         addBigNum(&result, &t);
138     }
139 
140     copyBigNum(&result, src);
141 
142     return 0;
143 }
144 
145 int main(){
146     bigNum src;
147     bigNum dst;
148     
149     makeBigNum(1, &src);
150     
151     for (int i=1; i<32; i++){
152         makeBigNum(i, &dst);
153         multiplyBigNum(&src, &dst);
154         printfBigNum(&src);
155     }
156 
157     getchar();
158     return 0;
159 }

 

posted @ 2012-10-08 22:17  simcity  阅读(1450)  评论(5编辑  收藏  举报