用 C# 完成的 BigNumber 类






4.80/5 (26投票s)
一个简单的 C# 库,用于进行任何所需精度的数学计算
引言
我想要编写一个简单的 C# 库,允许进行任意精度级别的数学计算。
背景
在过去的几个月里,我一直在研究数学库,并开始实现我自己的高精度数学库。我偶然发现了 MAPM 库 (http://www.tc.umn.edu/~ringx004/mapm-main.html),并决定为 .NET 创建一个类似的东西。这个库是我工作的成果。基本上,它是 MAPM 库在 .NET 上的重写。
我的目标是在我之前在 CodeProject 上发布的一个 Mandelbrot 分形渲染器 这里 中使用这个库。理论上,这应该提供无限地缩放到分形(以牺牲速度为代价)。我们很快就会看到会发生什么 ;-)
Using the Code
大数类的头部看起来像这样
public partial class BigNumber
{
sbyte signum=0;
int exponent=0;
byte[] mantissa= {0};
int dataLength=1;
...
}
大数以 S * A * 10 ^ B 的形式表示,其中
- S ... 是符号
- A ... 是尾数
- B ... 是指数
尾数表示为打包字节的数组。
每个字节的半字节代表数字的 2 位。
尾数可以具有任意长度。它限制为 1 < |a| < 10
打开项目,编译并运行。包含的测试程序将调用库的函数 DoTest()
。
查看 DoTest()
函数,了解如何使用这个库。您将找到如何
- 将值赋给
BigNumber
- 使用重载的运算符 +、-、* 和 / 进行基本的数学运算
- 使用像四舍五入、sqrt、pow、log10、log2 等数学函数
- 使用此库计算 1000!
- 计算 PI 到所需的位数
public static void DoTest()
{
BigNumber A = 0, B = 0, C = 0;
BigNumber PI= new BigNumber();
// assignment by string
A = "12345";
Console.WriteLine("assigned value was: " + A.ToFullString() +
"(" + A.ToString() + ")");
// assignment by double
A = 123.45;
Console.WriteLine("assigned value was: " + A.ToFullString() +
"(" + A.ToString() + ")");
// assignment by string in exponential form x = a*10^y. 10E3 = 10*10^^3 = 10000
A = "10E3"; // 10E3 = 10*10^3 = 10000
B = "1E4"; // 1E4 = 1*10^4 = 10000
C = 10000;
Console.WriteLine("assigned value was: " + A.ToFullString() +
"(" + A.ToString()+")");
Console.WriteLine("10000 = " + A.ToFullString() + " = " +
B.ToFullString() + " = " + C.ToFullString());
A = 1; B = 2; C = 0;
C = A + B;
Console.WriteLine("the result of " + A.ToFullString() + "+" +
B.ToFullString() + "=" + C.ToFullString());
// addition of BigNumber + double
C = A + 3.2;
// addition of double + BigNumber
C = 3.1 + B;
A = "5.141592"; B = "2.91827";
C = A - B;
Console.WriteLine("the result of " + A.ToFullString() +
"-" + B.ToFullString() + "=" + C.ToFullString());
C = A * B;
Console.WriteLine("the result of " + A.ToFullString() +
"*" + B.ToFullString() + "=" + C.ToFullString());
A = 5.0; B = 3.0;
C = A * B;
Console.WriteLine("the result of " + A.ToFullString() +
"*" + B.ToFullString() + "=" + C.ToFullString());
A = 4; B = 0.5;
C = A.Pow(B);
Console.WriteLine("the result of " + A.ToFullString() +
" pow " + B.ToFullString() + "=" + C.ToFullString());
A = 0.5; B = "5E-1";
C = A.Pow(B,16);
Console.WriteLine("the result of " + A.ToFullString() +
" pow " + B.ToFullString() + "=" + C.ToFullString());
A = "1e3"; // "10E2"; // "1E3 = 1000";
C = A.Log10();
Console.WriteLine("the result of " + A.ToFullString() +
" Log10 =" + C.ToFullString());
A = "10E3"; B = "1E4"; C=10000 ;
A = BigNumber.BN_E;
C = A.Log();
Console.WriteLine("the result of " + A.ToString() +
" Log =" + C.ToFullString());
A = 3.0;
C = A.Rez();
Console.WriteLine("the result of " + A.ToString() +
" Rez =" + C.ToFullString());
int NumPlaces = 4;
A = 1.53456;
C = A.Round(NumPlaces);
Console.WriteLine("the result of " + A.ToString() +
" Round(" + NumPlaces + ") =" +
C.ToFullString());
NumPlaces = 2;
C = A.Round(NumPlaces);
Console.WriteLine("the result of " + A.ToString() +
" Round(" + NumPlaces + ") =" +
C.ToFullString());
NumPlaces = 0;
C = A.Round(NumPlaces);
Console.WriteLine("the result of " + A.ToString() +
" Round(" + NumPlaces + ") =" +
C.ToFullString());
NumPlaces = 16;
A = 2.0;
C = A.Sqrt(NumPlaces);
Console.WriteLine("the result of " + A.ToString() +
" Sqrt(" + NumPlaces + ") =" +
C.ToFullString());
A = 1.0; B = 0;
try
{
C = A / B;
}
catch (BigNumberException ex)
{
Console.WriteLine("Exception in operation: " + ex.Message);
}
A = 1.0;
for (int i = 1; i <= 1000; i++)
{
A = A * i;
}
Console.WriteLine("the result of 1000!=" + A.ToFullString());
A = A.Round(numDefaultPlaces);
Console.WriteLine("the result of 1000!=" + A.ToString());
DateTime before = DateTime.Now;
NumPlaces = 5000;
CalculatePiAGM(PI, NumPlaces);
TimeSpan ts = DateTime.Now - before;
Console.WriteLine("time for "+NumPlaces+" digits of PI: " +
ts.TotalMilliseconds + "[ms]");
Console.WriteLine(PI.ToFullString());
Console.WriteLine("Press 'x' key to quit test");
while (true)
{
ConsoleKeyInfo i = Console.ReadKey();
if (i.KeyChar == 'x') break;
}
}
历史
- 31.08.2009
- 首次发布
- 03.09.2009
- 实现了从二进制和十六进制字符串设置值
- 修复了加法函数中的一个错误