




免费预览已结束,剩余1页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
再谈 BigInteger - 使用快速傅里叶变换我在“浅谈 BigInteger”的随笔中实现了一个 Skyiv.Numeric.BigInteger 类,那时乘法是使用常规的 O(N2) 的算法,所以比 .NET Framework 3.5 Base Class Library 中的 System.Numeric.BigInteger 类稍慢,后者的乘法是使用 Karatsuba 算法,其时间复杂度约为 O(N1.585)。现在,我已经实现了一个提供任意精度的算术运算的静态类: BigArithmetic,该类使用快速傅里叶变换计算大整数乘法,其时间复杂度降低到 O(N logN loglogN)。所以,Skyiv.Numeric.BigInteger 类也重新改写调用 BigArithmetic 类的静态方法来进行算术运算。下面就是改写后的 Skyiv.Numeric.BigInteger 类的源程序代码:复制代码 1 using System; 2 using System.Text; 3 4 namespace Skyiv.Numeric 5 6 sealed class BigInteger : IEquatable, IComparable 7 8 static readonly byte Len = 2; 9 static readonly byte Base = (byte)Math.Pow(10, Len); 10 11 sbyte sign; / 符号,取值:-1, 0, 1。 12 byte data; / 字节数组以 100 为基,字节数组中第一个元素存储的数字是最高有效位。 13 复制代码因为 BigArithmetic 类是对字节数组进行算术运算,字节数组以 100 为基,为了方便调用 BigArithmetic 类的静态方法进行算术运算,BigInteger 也改为使用以 100 为基的字节数组来存储。原来是使用 109 为基的 List 来存储的。我在改写过程中曾经使用过以 108 为基的 List 来存储,在需要调用 BigArithmetic 类的静态方法进行算术运算时将参数转换为以 100 为基的字节数组,运算完成后再将运算结果转换回来。这样做的好处是加法和减法运算比较快(还使用原来的方法,不调用 BigArithmetic 类的静态方法),并且除了 operator *、DivRem 和 Sqrt 方法以外,其他所有的方法都不用改写。不过经过综合考虑,还是采用现在的方案。 复制代码 14 BigInteger() 15 16 17 18 BigInteger(long x) 19 20 sign = (sbyte)(x = 0) ? 0 : (x 0) ? 1 : -1); 21 data = new byte10; / long.MinValue = -9,223,372,036,854,775,808 22 ulong z = (x 0) ? (ulong)-x : (ulong)x; 23 for (int i = data.Length - 1; z != 0; i-, z /= Base) datai = (byte)(z % Base); 24 Shrink(); 25 26 27 BigInteger(BigInteger x) 28 29 sign = x.sign; / x != null 30 data = new bytex.data.Length; 31 Array.Copy(x.data, data, data.Length); 32 33 34 public static implicit operator BigInteger(long x) 35 36 return new BigInteger(x); 37 38 复制代码私有的构造函数,和原来的大同小异。 复制代码 39 public static BigInteger Parse(string s) 40 41 if (s = null) return null; 42 s = s.Trim().Replace(, null); 43 if (s.Length = 0) return 0; 44 BigInteger z = new BigInteger(); 45 z.sign = (sbyte)(s0 = -) ? -1 : 1); 46 if (s0 = - | s0 = +) s = s.Substring(1); 47 int r = s.Length % Len; 48 z.data = new bytes.Length / Len + (r != 0) ? 1 : 0); 49 int i = 0; 50 if (r != 0) z.datai+ = byte.Parse(s.Substring(0, r); 51 for (; i z.data.Length; i+, r += Len) z.datai = byte.Parse(s.Substring(r, Len); 52 z.Shrink(); 53 return z; 54 55 复制代码静态的 Parse 方法,也和原来的大同小异。程序的第 56 到 95 行以及 111 到 116 行是 Abs、Pow 方法以及单目 +、-、+ 和 - 运算符,以及减法(-)运算符,和原来的相同。 复制代码 96 public static BigInteger operator +(BigInteger x, BigInteger y) 97 98 if (x = null | y = null) return null; 99 if (x.AbsCompareTo(y) 0) Utility.Swap(ref x, ref y);100 BigInteger z = new BigInteger();101 z.sign = x.sign;102 byte bs = Utility.Expand(y.data, x.data.Length);103 bool isAdd = x.sign * y.sign = 1;104 z.data = new bytex.data.Length + (isAdd ? 1 : 0);105 if (isAdd) BigArithmetic.Add(z.data, x.data, bs, bs.Length);106 else BigArithmetic.Subtract(z.data, x.data, bs, bs.Length);107 z.Shrink();108 return z;109 110 复制代码加法(+)运算符,调用 BigArithmetic 类的 Add 和 Subtract 方法。复制代码117 public static BigInteger operator *(BigInteger x, BigInteger y)118 119 if (x = null | y = null) return null;120 if (x.sign * y.sign = 0) return 0;121 BigInteger z = new BigInteger();122 z.sign = (sbyte)(x.sign * y.sign);123 z.data = new bytex.data.Length + y.data.Length;124 BigArithmetic.Multiply(z.data, x.data, x.data.Length, y.data, y.data.Length);125 z.Shrink();126 return z;127 128 复制代码乘法(*)运算,直接调用 BigArithmetic 类的 Multiply 方法。程序的第 129 到 141 行是 / 和 % 运算符,和原来的相同。 复制代码142 public static BigInteger DivRem(BigInteger dividend, BigInteger divisor, out BigInteger remainder)143 144 remainder = null;145 if (dividend = null | divisor = null) return null;146 if (divisor.sign = 0) throw new DivideByZeroException();147 if (dividend.AbsCompareTo(divisor) 0)148 149 remainder = new BigInteger(dividend);150 return 0;151 152 BigInteger quotient = new BigInteger();153 remainder = new BigInteger();154 quotient.data = new bytedividend.data.Length - divisor.data.Length + 1;155 remainder.data = new divisor.data.Length;156 BigArithmetic.DivRem(quotient.data, remainder.data, dividend.data,157 dividend.data.Length, divisor.data, divisor.data.Length);158 quotient.sign = (sbyte)(dividend.sign * divisor.sign);159 remainder.sign = dividend.sign;160 quotient.Shrink();161 remainder.Shrink();162 return quotient;163 164 复制代码静态的 DevRem 方法,也是调用 BigArithmetic 类的 DivRem 方法。 复制代码165 public static BigInteger Sqrt(BigInteger x)166 167 if (x = null | x.sign 0) return null;168 if (x.sign = 0) return 0;169 if (x.data.Length = 1) return new BigInteger(long)Math.Sqrt(x.data0);170 BigInteger z = new BigInteger();171 z.sign = 1;172 z.data = new bytex.data.Length / 2 + 3;173 z.data = Adjust(BigArithmetic.Sqrt(z.data, z.data, z.data.Length, x.data, x.data.Length), x.data.Length);174 z.Shrink();175 BigInteger z1 = z + 1; / 平方根有可能比实际小 1。176 return (z1 * z1 = 10) throw new OverflowException(sqrt adjust);182 byte nbs = new byte(digits + 1) / 2;183 if (digits % 2 = 0)184 for (int k = bs0, i = 0; i nbs.Length; i+, k = bsi % 10)185 nbsi = (byte)(k * 10 + bsi + 1 / 10);186 else Array.Copy(bs, nbs, nbs.Length);187 return nbs;188 189 复制代码求平方根(Sqrt),调用 BigArithmetic 类的 Sqrt 方法。但是要注意,BigArithmetic 类的 Sqrt 方法求得的平方根是小数,需要使用 Adjust 方法调整为整数。并且平方根有可能比实际的小 1,也需要判断和调整。 复制代码190 void Shrink()191 192 int i;193 for (i = 0; i data.Length; i+) if (datai != 0) break;194 if (i != 0)195 196 byte bs = new bytedata.Length - i;197 Array.Copy(data, i, bs, 0, bs.Length);198 data = bs;199 200 if (data.Length = 0) sign = 0;201 202 复制代码私有的 Shrink 方法用于在需要时收缩存储数据的字节数组。程序的第 203 到 238 行是各种逻辑运算符,和原来的完全一样。复制代码239 public override string ToString()240 241 StringBuilder sb = new StringBuilder();242 if (sign 0) Append(-);243 sb.Append(data.Length = 0) ? 0 : (int)data0);244 for (int i = 1; i data.Length; i+) sb.Append(datai.ToString(D + Len);245 return sb.ToString();246 247 复制代码从基类继承的 ToString 方法,和原来的大同小异。程序的第 248 到 274 行是从基类继承的 GetHashCode、Equals 方法,以及用于实现接口的 Equals 和 CompareTo 方法,和原来的相同。 复制代码275 int AbsCompareTo(BigInteger other)276 277 if (data.Length other.data.Length) return 1;279
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年计算机四级真题及答案详解(夺冠系列)
- 绿色金融政策协同效应2025:市场现状与支持体系研究报告
- 半导体研发生产基地项目实施方案
- 绿色金融支持2025年生物质能发电项目的创新路径分析
- 2025年执业药师之《西药学专业一》预测试题完整答案详解
- 绿色金融推动绿色金融产品创新与风险管理体系的构建
- 2025年施工员模拟试题及参考答案详解(培优)
- 2025年户外广告牌制作合同3篇
- 2025年公需科目考试题(附答案)
- 重难点自考专业(行政管理)试题附答案【达标题】
- 2025年公证员助理招聘考试题库及模拟题答案
- 初二入团考试内容及答案
- 针灸科感控知识培训课件
- 微生物学讲课文档
- 2025年湖北省武汉市中考物理试卷(含答案与解析)
- 婴幼儿发展引导员岗前考核试卷及答案
- 2025湖北省监督数据分析应用中心专项招聘22人考试参考试题及答案解析
- 汽车维修工国家职业资格二级技能试题(附答案)
- 2025年秋期新部编人教版五年级上册道德与法治教学计划+进度表
- 文创市集限定摊位协议
- 2025版旅游景区导游及服务人员派遣合同模板
评论
0/150
提交评论