📄 ubiginteger.cs
字号:
using System;
using System.Text;
#region 版权声明
///
/// 版权所有(C)2005,2006 作者:漆巧林。保留所有权利, davidqql@gmail.com, davidqql@hotmail.com
///
/// 作者不对本代码提供任何保证,因此,对于使用该代码带来的损害或者潜在的损害,作者不承担责任。
/// 在满足如下的条件下,你可以自由使用该代码:
/// 1. 非商业应用
/// 2. 保留本版权声明
/// 要进行商业应用,必须得到作者的书面许可。
/// 你可以修改和自由发布本代码,条件是保留前述的版权声明。
///
#endregion
namespace BizSecurity
{
/// <summary>
/// UBigInteger :无符号大整数,其长度最多为2^31个位(以0x100000000进制计算)。
/// </summary>
public class UBigInteger
{
#region 常量区
public static readonly Char[] LowerHexCharMapping =
{
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
public static readonly Char[] UpperHexCharMapping =
{
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
public static readonly uint[] PrimeTable =
{
3, 5, 7, 11, 13, 17, 19, 23, 29, 31,
37, 41, 43, 47, 53, 59, 61, 67, 71, 73,
79, 83, 89, 97, 101, 103, 107, 109, 113, 127,
131, 137, 139, 149, 151, 157, 163, 167, 173, 179,
181, 191, 193, 197, 199, 211, 223, 227, 229, 233,
239, 241, 251, 257, 263, 269, 271, 277, 281, 283,
293, 307, 311, 313, 317, 331, 337, 347, 349, 353,
359, 367, 373, 379, 383, 389, 397, 401, 409, 419,
421, 431, 433, 439, 443, 449, 457, 461, 463, 467,
479, 487, 491, 499, 503, 509, 521, 523, 541, 547,
557, 563, 569, 571, 577, 587, 593, 599, 601, 607,
613, 617, 619, 631, 641, 643, 647, 653, 659, 661,
673, 677, 683, 691, 701, 709, 719, 727, 733, 739,
743, 751, 757, 761, 769, 773, 787, 797, 809, 811,
821, 823, 827, 829, 839, 853, 857, 859, 863, 877,
881, 883, 887, 907, 911, 919, 929, 937, 941, 947,
953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019,
1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087,
1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153,
1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229,
1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297,
1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381,
1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453,
1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523,
1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597,
1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663,
1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741,
1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823,
1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901,
1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993,
1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063,
2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131,
2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221,
2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293,
2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371,
2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437,
2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539,
2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621,
2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689,
2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749,
2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, 2833,
2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 2909,
2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001,
3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083,
3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187,
3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259,
3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343,
3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433,
3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517,
3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581,
3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, 3659,
3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733,
3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823,
3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911,
3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001
};
#endregion
static Random random;
private int nCapacity; // 最大容量
private int nLength; // 长度(按2^32进制计算)
private uint[] values; // 各个数字位取值
static UBigInteger()
{
random = new Random();
}
/// <summary>
/// 默认构造函数:创建一个1024位的无符号整数
/// </summary>
public UBigInteger()
: this(32)
{
}
/// <summary>
/// 指定最大容量构造无符号大整数
/// </summary>
/// <param name="capacity">指定的容量</param>
public UBigInteger(int capacity) // 指定容量的构造函数
{
nLength = 0;
nCapacity = capacity;
values = new uint[nCapacity];
}
/// <summary>
/// 从其他实例构造副本实例
/// </summary>
/// <param name="other">其他大整数实例</param>
public UBigInteger(UBigInteger other) // 从其他实例构造
:this(other.nCapacity)
{
nLength = other.nCapacity - other.nLength;
while(nLength < nCapacity)
{
values[nLength] = other.values[nLength];
nLength ++;
}
nLength = other.nLength;
}
/// <summary>
/// 判断与一个object对象是否相等,重载object的Equals
/// </summary>
/// <param name="obj">用于比较的对象</param>
/// <returns>如果两个对象相等,返回真值,否则返回假</returns>
public override bool Equals(object obj)
{
if(obj is UBigInteger)
{
return this == (UBigInteger)obj;
}
return false;
}
/// <summary>
/// 重载object类的HashCode
/// </summary>
/// <returns>返回基类的HashCode</returns>
public override int GetHashCode()
{
return base.GetHashCode ();
}
#region 属性区
/// <summary>
/// 获取当前大整数长度(以0x100000000进制计算)
/// </summary>
public int Length
{
get { return nLength; }
}
/// <summary>
/// 获取二进制位数长度
/// </summary>
public int BitLength
{
get
{
if(nLength == 0)
return 0;
uint highest = values[nCapacity - nLength];
int bits = nLength * 32;
uint bit = 0xFF000000;
while(bit > 0 && (highest & bit)==0)
{
bit >>= 8;
bits -= 8;
}
return bits;
}
}
/// <summary>
/// 获取大整数的当前最大容量
/// </summary>
public int Capacity
{
get { return nCapacity; }
}
/// <summary>
/// 设置当前大整数实例,拷贝其他实例的数据
/// </summary>
public UBigInteger Item
{
set
{
if(nCapacity < value.nCapacity)
{
nCapacity = value.nCapacity;
values = new uint[nCapacity];
}
int nOther = value.nCapacity;
int nThis = nCapacity;
int nNumber = value.nLength;
while(nNumber-- > 0)
{
values[--nThis] = value.values[--nOther];
}
while(nThis > 0)
{
values[--nThis] = 0;
}
nLength = value.nLength;
}
}
#endregion
#region 重载运算符区
/// <summary>
/// operator +,两个大整数相加
/// </summary>
/// <param name="augend">被加数</param>
/// <param name="addend">加数</param>
/// <returns>返回相加之后的结果,不改变加数和被加数的值</returns>
public static UBigInteger operator +(UBigInteger augend, UBigInteger addend)
{
int maxLength;
if(augend.nLength > addend.nLength)
{
maxLength = augend.nLength >= augend.nCapacity ? augend.nCapacity + 1 : augend.nCapacity;
}
else
{
maxLength = addend.nLength >= addend.nCapacity ? addend.nCapacity + 1 : addend.nCapacity;
}
UBigInteger result = new UBigInteger(maxLength);
ulong sum;
uint carry = 0;
int nAugend = augend.nLength;
int nAddend = addend.nLength;
int nStartAugend = augend.nCapacity;
int nStartAddend = addend.nCapacity;
while((nAugend > 0) && (nAddend > 0))
{
sum = augend.values[--nStartAugend];
sum += addend.values[--nStartAddend];
sum += carry;
result.values[--maxLength] = (uint)sum;
carry = (uint)(sum >> 32);
nAugend --;
nAddend --;
}
while(nAddend > 0)
{
sum = addend.values[--nStartAddend];
sum += carry;
result.values[--maxLength] = (uint)sum;
carry = (uint)(sum >> 32);
nAddend --;
}
while(nAugend > 0)
{
sum = augend.values[--nStartAugend];
sum += carry;
result.values[--maxLength] = (uint)sum;
carry = (uint)(sum >> 32);
nAugend --;
}
if(carry > 0)
{
result.values[--maxLength] = carry;
}
result.nLength = result.nCapacity - maxLength;
return result;
}
/// <summary>
/// 大整数加无符号整数
/// </summary>
/// <param name="augend">被加数(大整数)</param>
/// <param name="addend">加数(无符号整数)</param>
/// <returns>返回相加之后的结果</returns>
public static UBigInteger operator +(UBigInteger augend, uint addend)
{
UBigInteger result;
if(augend.nLength > augend.nCapacity)
{
result = new UBigInteger(augend.nCapacity + 1);
}
else
{
result = new UBigInteger(augend.nCapacity);
}
int nEnd = augend.nCapacity;
int nResultEnd = result.nCapacity;
int nNumber = augend.nLength;
while(addend > 0 && nNumber > 0)
{
ulong sum = augend.values[--nEnd];
sum += addend;
result.values[--nResultEnd] = (uint)sum;
addend = (uint)(sum >> 32);
nNumber --;
}
if(addend > 0)
{
result.values[--nResultEnd] = addend;
}
while(nNumber -- > 0)
{
result.values[--nResultEnd] = augend.values[--nEnd];
}
result.nLength = result.nCapacity - nResultEnd;
return result;
}
/// <summary>
/// 重载两国大整数相减运算符
/// </summary>
/// <param name="minuend">被减数</param>
/// <param name="subtrahend">减数</param>
/// <returns>返回被减数和减数相减的结果,如果被减数小于减数,将返回零</returns>
public static UBigInteger operator -(UBigInteger minuend, UBigInteger subtrahend)
{
UBigInteger result = new UBigInteger(minuend.nLength);
if((minuend <= subtrahend))
{
return result;
}
int nEndLeft = minuend.nCapacity;
int nEndRight = subtrahend.nCapacity;
int nLeftLength = minuend.nLength;
int nRightLength = subtrahend.nLength;
int nEndResult = result.nCapacity;
ulong temp = 0;
uint carry = 0;
while(nRightLength > 0)
{
uint nLeft = minuend.values[--nEndLeft];
uint nRight = subtrahend.values[--nEndRight];
if(nLeft < nRight || nLeft == nRight && carry > 0)
{
temp = 0x100000000u + nLeft;
result.values[--nEndResult] = (uint)(temp - nRight - carry);
carry = 1;
}
else
{
result.values[--nEndResult] = (uint)(nLeft - nRight - carry);
carry = 0;
}
nLeftLength --;
nRightLength --;
}
if(carry > 0)
{
while(minuend.values[--nEndLeft] == 0)
{
result.values[--nEndResult] = 0xffffffff;
nLeftLength --;
}
result.values[--nEndResult] = minuend.values[nEndLeft] - 1;
nLeftLength --;
}
while(nLeftLength -- >0)
{
result.values[--nEndResult] = minuend.values[--nEndLeft];
}
while(result.values[nEndResult] == 0)
{
nEndResult ++;
}
result.nLength = result.nCapacity - nEndResult;//nStart;
return result;
}
/// <summary>
/// 大整数减去一个无符号整数
/// </summary>
/// <param name="minuend">被减数</param>
/// <param name="subtrahend">减数</param>
/// <returns>返回大整数减去无符号整数的结果</returns>
public static UBigInteger operator -(UBigInteger minuend, uint subtrahend)
{
UBigInteger result = new UBigInteger(minuend);
if(minuend.nLength == 0)
return result;
int nEnd = result.nCapacity - 1;
if(result.values[nEnd] > subtrahend)
{
result.values[nEnd] -= subtrahend;
return result;
}
if(minuend.nLength == 1)
{
result.Assign(0);
return result;
}
ulong temp = 0x100000000u + result.values[nEnd];
result.values[nEnd] = (uint)(temp - subtrahend);
while(result.values[--nEnd] ==0)
{
result.values[nEnd] = 0xffffffff;
}
result.values[nEnd] --;
if(result.values[nEnd] == 0)
result.nLength --;
return result;
}
/// <summary>
/// 重载运算符*进行大整数相乘
/// </summary>
/// <param name="faciend">被乘数</param>
/// <param name="multiplier">乘数</param>
/// <returns>返回两个大整数相乘的结果</returns>
public static UBigInteger operator *(UBigInteger faciend, UBigInteger multiplier)
{
int maxLength;
maxLength = faciend.nLength + multiplier.nLength;
UBigInteger result = new UBigInteger(maxLength);
int nRight = multiplier.nLength;
int nEndRight = multiplier.nCapacity;
while(nRight -- > 0)
{
uint nMultiplier = multiplier.values[--nEndRight];
int nEndLeft = faciend.nCapacity;
maxLength --;
int nResultPos = maxLength;
ulong mul;
uint carry = 0;
int nLeft = faciend.nLength;
while(nLeft -- >0)
{
mul = faciend.values[--nEndLeft];
mul *= nMultiplier;
mul += carry;
carry = (uint)(mul >> 32);
int nEndResult = nResultPos;
while(carry > 0)
{
ulong temp = result.values[--nEndResult];
temp += carry;
result.values[nEndResult] = (uint)(temp);
carry = (uint)(temp >> 32);
}
mul &= 0xffffffff;
mul += result.values[nResultPos];
result.values[nResultPos] = (uint)mul;
carry = (uint)(mul >> 32);
nEndResult = nResultPos;
while(carry > 0)
{
ulong temp = result.values[--nEndResult];
temp += carry;
result.values[nEndResult] = (uint)(temp);
carry = (uint)(temp >> 32);
}
nResultPos --;
}
}
result.RefreshLength();
return result;
}
/// <summary>
/// 大整数和无符号整数相乘
/// </summary>
/// <param name="faciend">被乘数</param>
/// <param name="multiplier">乘数</param>
/// <returns>返回一个大整数,该大整数是被乘数和乘数相乘的结果</returns>
public static UBigInteger operator *(UBigInteger faciend, uint multiplier)
{
int nLenResult;
if(faciend.nLength >= faciend.nCapacity)
{
nLenResult = faciend.nCapacity+ 1;
}
else
{
nLenResult = faciend.nCapacity;
}
UBigInteger result = new UBigInteger(nLenResult);
int nLoop = faciend.nLength;
int nEnd = faciend.nCapacity;
ulong sum = 0;
uint carry = 0;
while(nLoop -- > 0)
{
sum = faciend.values[--nEnd];
sum *= multiplier;
sum += carry;
result.values[--nLenResult] = (uint)sum;
carry = (uint)(sum >> 32);
}
if(carry > 0)
{
result.values[--nLenResult] = carry;
}
result.RefreshLength();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -