root/trunk/Bignumber/Bignumber.d

Revision 307, 10.5 kB (checked in by yidabu, 4 years ago)

D China domain changed

Line 
1 /*******************************************************************************
2         copyright:      Copyright (c) 2007  (yidabu  g m a i l at com) All rights reserved
3
4         license:        BSD style: $(LICENSE)
5
6         version:        Initial release: 2007
7
8         author:         modified by yidabu ( D China : http://www.d-programming-language-china.org/ )
9         original post:  http://www.fenglin.info/gen_ex/53/Algorithm/323345.html
10
11 *******************************************************************************/
12
13 /**
14     TODO:
15         1. very low  efficiency of opDiv now.
16     Examples:
17     ---
18         auto a = new Bignumber("12345678901234567890123456789012345678901234567890");
19         auto b = new Bignumber("12345678901234567890123456789012345678901234567890");
20         auto c = a - b;
21         Trace("a - b = ")( c.toUtf8() ).newline;
22         
23         c = a + b -b;
24         Trace("a + b - b = ")( c.toUtf8() ).newline;
25         
26         c = a * b / b;     
27         Trace("a * b / b = ")( c.toUtf8() ).newline;
28         
29         c = a / b * b;
30         Trace("a / b * b = ")( c.toUtf8() ).newline;   
31     ---
32 */
33 // module dwin.lab.Bignumber;
34 module Bignumber.Bignumber; // it's in the Bignumber folder, it has the Bignumber package. Easy as pie.
35
36 version(Tango) {
37     import tango.text.convert.Integer;
38     debug( UnitTest ) import tango.util.log.Trace; 
39 } else {
40     import std.math, std.string, std.stdio;
41     struct _Trace { _Trace opCall(T)(T t) { writef(t); return *this; } void newline() { writefln(); } }
42     struct Trace { static _Trace opCall(T)(T t) { writef(t); _Trace bogus; return bogus; } }
43 }
44
45 class Bignumber
46 { 
47 public: 
48     enum : uint {BASELEN = 3U,BASE = 1_000_000U};
49     enum : uint {MAX = 100U};      //i'm thinking change this to dynamic array if  possible....
50     uint data[MAX];   //initialize as 0
51     uint len;         //initialize as 0 
52     int  sign;        //initialize as 0   ; 0: positive; 1: negative
53    
54     this (Bignumber b){
55         Assign(b);
56     }
57     void Assign(Bignumber b)
58     {
59         len = b.len;
60         sign = b.sign;
61         data[]=b.data[];
62     }
63     this(int num = 0){                 
64         if(num == 0){len = 1;return;}
65         if(num < 0){
66             sign = 1;
67             num = -num;
68         }       
69         while(num > 0){           
70             data[len++] = num % BASE;
71             num /= BASE;
72         }
73     }
74      
75     this(char[] num){       
76         if(num.length == 0) {len = 1;return;}
77         int beg = 0;       
78         switch(num[0]){
79             case '-': {sign = 1;};
80             case '+': {++beg;} ;
81             default : break;
82         }
83         int i = num.length - BASELEN;
84         for(; i >= beg; i -= BASELEN){     
85             char[] tmp = num[i..i+BASELEN];
86             data[len++] = atoi(tmp);
87             //data[len++] = std.conv.toUint(tmp);
88         }
89         i += BASELEN;
90         if(i>beg){
91             char[] tmp = num[0..i];
92             data[len++] = atoi(tmp);
93             //data[len++] = std.conv.toUint(tmp);
94         }       
95     }
96      
97     Bignumber opNeg()
98     {
99         Bignumber ret = new Bignumber(this);
100         ret.sign ^= 1;
101         return ret;
102     }
103          
104     int opEquals(Bignumber b){
105         if(sign != b.sign || len != b.len) return 0;
106         return data == b.data;         
107     }
108      
109     int absCmp(Bignumber b, Bignumber r){
110         if(b.len>r.len) return 1;
111         else if(b.len<r.len) return 0;       
112          
113         for(int i = b.len-1;i >= 0; i--){
114             if(b.data[i] > r.data[i])
115                 return 1;
116             else if(b.data[i] < r.data[i]) return 0;
117         }
118         return 0;       
119     }
120      
121     int opCmp(Bignumber b)
122     {
123         if(sign < b.sign) return 1;
124         else if(sign > b.sign) return 0;       
125         if(sign == 0) return absCmp(this,b);
126         else return 1&absCmp(b,this);               
127     }
128          
129      // +
130     Bignumber opAdd(Bignumber b)
131     {
132         if(sign!=b.sign) {
133             b.sign ^= 1;
134             Bignumber ret = this-b;
135             b.sign ^= 1;
136             return ret;
137         }
138         Bignumber ret = new Bignumber();
139         ret.sign = sign;
140         uint tmp = 0;
141         uint i;
142         for(i = 0; i<b.len && i<len; i++) {
143             ret.data[i]= (data[i] + b.data[i] + tmp) % BASE;
144             tmp = (data[i] + b.data[i] + tmp) / BASE;
145         }
146         void residual(uint len,uint data[]) {
147             for(;i < len; i++) {
148                 ret.data[i] = (tmp + data[i]) % BASE;
149                 tmp = (tmp + data[i]) / BASE;
150             }
151         }
152         if(i < len)
153             residual(len, data);                             
154         else if(i < b.len)
155             residual(b.len, b.data);
156         ret.len = i;       
157         if(tmp) ret.data[ret.len++] = tmp;         
158         return ret;     
159     }
160          
161     // -
162     Bignumber opSub(Bignumber b)
163     {                                 
164         if(sign != b.sign){
165             b.sign ^= 1;
166             Bignumber ret = this + b;   
167             b.sign ^= 1;
168             return ret;
169         }
170         Bignumber big,small;
171         Bignumber ret = new Bignumber();
172         Bignumber absSub(Bignumber big,Bignumber small){  //assume big > small           
173             int tmp = 0;
174             uint i;         
175             ret.len = big.len;
176             for(i = 0;i<small.len&&i<big.len;i++){ 
177            
178                 uint t = small.data[i]+tmp;
179                 tmp = (t>big.data[i]);
180                 ret.data[i]=(BASE&(-tmp))+big.data[i]-t;
181             }                   
182             for(;i<big.len;i++){
183                 uint t = tmp;
184                 tmp = (t>big.data[i]);
185                 ret.data[i]=(BASE&(-tmp))+big.data[i]-t;                   
186      
187             }
188             while(ret.data[ret.len-1] == 0&&ret.len>1)
189                 ret.len--;     
190             return ret;
191         }                   
192         if(absCmp(this,b)){         
193             big = this;small = b;
194             ret.sign = sign;
195         }else{           
196             small = this;big = b;
197             ret.sign = sign^1;
198         }                                               
199         return absSub(big,small);
200     }
201          
202     // *
203     Bignumber opMul(Bignumber b){
204         Bignumber ret = new Bignumber;
205         ret.sign = (b.sign^sign);
206         ret.len = (len+b.len-1);
207         uint tmp = 0;
208          
209         for(uint i = 0;i<len;i++){
210             for(int j = 0;j<b.len;j++){
211                 int c;               
212                 c = (ret.data[i+j]+data[i]*b.data[j]+tmp)/BASE;
213                 //writefln(data[i],",",b.data[j],"; ",data[i]*b.data[j]);
214                  
215                 ret.data[i+j]=(ret.data[i+j]+data[i]*b.data[j]+tmp)%BASE;       
216          
217                 tmp = c;
218             }           
219         }               
220         if(tmp)
221             ret.data[ret.len++]=tmp;
222         while(ret.data[ret.len-1] == 0&&ret.len>1) ret.
223             len--; 
224         return ret;
225     }
226          
227     // /
228     Bignumber opDiv(Bignumber b){
229         Bignumber ret = new Bignumber;
230         if( len < b.len) return ret;       
231         ret.sign = (b.sign ^ sign);       
232         ret.len = len-b.len+1;
233         Bignumber tmp = new Bignumber(this);       
234         tmp >>= (len-b.len+1);         
235         int i = len-b.len;
236         for(; i >= 0; i--){
237             tmp <<= 1;             
238             tmp = tmp + new Bignumber(data[i]);
239             Bignumber c2 = new Bignumber(b);
240             int j = 1;
241             for(; c2 <= tmp && j < BASE; j++, c2 = c2+b){};
242             //very low  efficiency,use binary search will be better
243             j--;
244             ret.data[i]=j;                       
245             tmp = (tmp-c2+b);         
246         }
247         while(ret.data[ret.len-1] ==0 && ret.len > 1) ret.len--; 
248         return ret;
249     }
250      
251      
252     Bignumber opAddAssign(Bignumber b)
253     {
254         Bignumber tmp = this + b;
255         Assign(tmp);
256         return this;
257     }
258      
259     Bignumber opSubAssign(Bignumber b)
260     {
261         Bignumber tmp = this - b;
262         Assign(tmp);
263         return this;
264     }
265      
266     Bignumber opMulAssign(Bignumber b)
267     {
268         Bignumber tmp = this * b;
269         Assign(tmp);
270         return this;
271     }
272     Bignumber opDivAssign(Bignumber b)
273     {
274         Bignumber tmp = this / b;
275         Assign(tmp);
276         return this;
277     }
278     Bignumber opShr(uint s)
279     {
280         Bignumber ret = new Bignumber(this);
281         ret>>=s;
282         return ret;
283     }
284      
285     Bignumber opShrAssign(uint s){
286         uint i;
287         for(i = 0;i<(len-s);i++)
288             data[i]=data[i+s];       
289         for(;i<len;i++)data[i]=0;
290         len-=s;
291         return this;
292     }
293          
294     Bignumber opShlAssign(uint s){
295         assert(len+s<MAX);
296         int i;                       
297         for(i = len-1;i>=0;i--)       
298             data[i+s]=data[i];       
299         for(i = 0;i<s;i++) data[i]=0;
300         len+=s;
301         return this;
302     }
303      
304     Bignumber opShl(uint s)
305     {
306         Bignumber ret = new Bignumber(this);
307         ret<<=s;
308         return ret;
309     }
310      
311     //char[] toString(){
312     char[] toUtf8(){
313         char[64] tmp;
314         char[] ret;
315         if(sign) ret~="-";
316         else     ret~="+";
317         for(int i = len-1; i >= 0; i--){
318             ret~= .toString(data[i]) ~ ",";
319         }
320         //ret ~= "BASE:"~ .toString(BASE);
321         //ret ~= "BASE:"~ itoa(tmp, BASE);
322         return ret;     
323     }
324 } 
325
326 Bignumber sqrt(Bignumber b) {
327     Bignumber res;
328     auto one = new Bignumber("1"), two = new Bignumber("2"); // sorry
329     res = (b+one) / two; // init
330     // writefln((b+one).toUtf8, " / ", two.toUtf8, " = ", res.toUtf8); // hey look! opDiv is broken!
331     auto r = new Bignumber("");
332     while (res>r) { res -= r; r += one; }
333     delete r;
334     return res;
335 }
336
337 debug( UnitTest ) unittest
338 { 
339     auto a = new Bignumber("12345678901234567890123456789012345678901234567890");
340     auto b = new Bignumber("12345678901234567890123456789012345678901234567890");
341     auto c = a - b;
342     Trace("a - b = ")( c.toUtf8() ).newline;
343    
344     c = a + b -b;
345     Trace("a + b - b = ")( c.toUtf8() ).newline;
346    
347     c = a * b / b;     
348     Trace("a * b / b = ")( c.toUtf8() ).newline;
349    
350     c = a / b * b;
351     Trace("a / b * b = ")( c.toUtf8() ).newline;
352    
353     Trace(sqrt(new Bignumber("65536")).toUtf8).newline;
354 } 
355
356 void main() { }
Note: See TracBrowser for help on using the browser.