📄 biginteger.cs
字号:
//***********************************************************************
// Overloading of division operator
//***********************************************************************
public static BigInteger operator /(BigInteger bi1, BigInteger bi2)
{
BigInteger quotient = new BigInteger();
BigInteger remainder = new BigInteger();
int lastPos = maxLength - 1;
bool divisorNeg = false, dividendNeg = false;
if ((bi1.data[lastPos] & 0x80000000) != 0) // bi1 negative
{
bi1 = -bi1;
dividendNeg = true;
}
if ((bi2.data[lastPos] & 0x80000000) != 0) // bi2 negative
{
bi2 = -bi2;
divisorNeg = true;
}
if (bi1 < bi2)
{
return quotient;
}
else
{
if (bi2.dataLength == 1)
singleByteDivide(bi1, bi2, quotient, remainder);
else
multiByteDivide(bi1, bi2, quotient, remainder);
if (dividendNeg != divisorNeg)
return -quotient;
return quotient;
}
}
//***********************************************************************
// Overloading of modulus operator
//***********************************************************************
public static BigInteger operator %(BigInteger bi1, BigInteger bi2)
{
BigInteger quotient = new BigInteger();
BigInteger remainder = new BigInteger(bi1);
int lastPos = maxLength - 1;
bool dividendNeg = false;
if ((bi1.data[lastPos] & 0x80000000) != 0) // bi1 negative
{
bi1 = -bi1;
dividendNeg = true;
}
if ((bi2.data[lastPos] & 0x80000000) != 0) // bi2 negative
bi2 = -bi2;
if (bi1 < bi2)
{
return remainder;
}
else
{
if (bi2.dataLength == 1)
singleByteDivide(bi1, bi2, quotient, remainder);
else
multiByteDivide(bi1, bi2, quotient, remainder);
if (dividendNeg)
return -remainder;
return remainder;
}
}
//***********************************************************************
// Overloading of bitwise AND operator
//***********************************************************************
public static BigInteger operator &(BigInteger bi1, BigInteger bi2)
{
BigInteger result = new BigInteger();
int len = (bi1.dataLength > bi2.dataLength) ? bi1.dataLength : bi2.dataLength;
for (int i = 0; i < len; i++)
{
uint sum = (uint)(bi1.data[i] & bi2.data[i]);
result.data[i] = sum;
}
result.dataLength = maxLength;
while (result.dataLength > 1 && result.data[result.dataLength - 1] == 0)
result.dataLength--;
return result;
}
//***********************************************************************
// Overloading of bitwise OR operator
//***********************************************************************
public static BigInteger operator |(BigInteger bi1, BigInteger bi2)
{
BigInteger result = new BigInteger();
int len = (bi1.dataLength > bi2.dataLength) ? bi1.dataLength : bi2.dataLength;
for (int i = 0; i < len; i++)
{
uint sum = (uint)(bi1.data[i] | bi2.data[i]);
result.data[i] = sum;
}
result.dataLength = maxLength;
while (result.dataLength > 1 && result.data[result.dataLength - 1] == 0)
result.dataLength--;
return result;
}
//***********************************************************************
// Overloading of bitwise XOR operator
//***********************************************************************
public static BigInteger operator ^(BigInteger bi1, BigInteger bi2)
{
BigInteger result = new BigInteger();
int len = (bi1.dataLength > bi2.dataLength) ? bi1.dataLength : bi2.dataLength;
for (int i = 0; i < len; i++)
{
uint sum = (uint)(bi1.data[i] ^ bi2.data[i]);
result.data[i] = sum;
}
result.dataLength = maxLength;
while (result.dataLength > 1 && result.data[result.dataLength - 1] == 0)
result.dataLength--;
return result;
}
//***********************************************************************
// Returns max(this, bi)
//***********************************************************************
public BigInteger max(BigInteger bi)
{
if (this > bi)
return (new BigInteger(this));
else
return (new BigInteger(bi));
}
//***********************************************************************
// Returns min(this, bi)
//***********************************************************************
public BigInteger min(BigInteger bi)
{
if (this < bi)
return (new BigInteger(this));
else
return (new BigInteger(bi));
}
//***********************************************************************
// Returns the absolute value
//***********************************************************************
public BigInteger abs()
{
if ((this.data[maxLength - 1] & 0x80000000) != 0)
return (-this);
else
return (new BigInteger(this));
}
//***********************************************************************
// Returns a string representing the BigInteger in base 10.
//***********************************************************************
public override string ToString()
{
return ToString(10);
}
//***********************************************************************
// Returns a string representing the BigInteger in sign-and-magnitude
// format in the specified radix.
//
// Example
// -------
// If the value of BigInteger is -255 in base 10, then
// ToString(16) returns "-FF"
//
//***********************************************************************
public string ToString(int radix)
{
if (radix < 2 || radix > 36)
throw (new ArgumentException("Radix must be >= 2 and <= 36"));
string charSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string result = "";
BigInteger a = this;
bool negative = false;
if ((a.data[maxLength - 1] & 0x80000000) != 0)
{
negative = true;
try
{
a = -a;
}
catch (Exception) { }
}
BigInteger quotient = new BigInteger();
BigInteger remainder = new BigInteger();
BigInteger biRadix = new BigInteger(radix);
if (a.dataLength == 1 && a.data[0] == 0)
result = "0";
else
{
while (a.dataLength > 1 || (a.dataLength == 1 && a.data[0] != 0))
{
singleByteDivide(a, biRadix, quotient, remainder);
if (remainder.data[0] < 10)
result = remainder.data[0] + result;
else
result = charSet[(int)remainder.data[0] - 10] + result;
a = quotient;
}
if (negative)
result = "-" + result;
}
return result;
}
//***********************************************************************
// Returns a hex string showing the contains of the BigInteger
//
// Examples
// -------
// 1) If the value of BigInteger is 255 in base 10, then
// ToHexString() returns "FF"
//
// 2) If the value of BigInteger is -255 in base 10, then
// ToHexString() returns ".....FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01",
// which is the 2's complement representation of -255.
//
//***********************************************************************
public string ToHexString()
{
string result = data[dataLength - 1].ToString("X");
for (int i = dataLength - 2; i >= 0; i--)
{
result += data[i].ToString("X8");
}
return result;
}
//***********************************************************************
// Modulo Exponentiation
//***********************************************************************
public BigInteger modPow(BigInteger exp, BigInteger n)
{
if ((exp.data[maxLength - 1] & 0x80000000) != 0)
throw (new ArithmeticException("Positive exponents only."));
BigInteger resultNum = 1;
BigInteger tempNum;
bool thisNegative = false;
if ((this.data[maxLength - 1] & 0x80000000) != 0) // negative this
{
tempNum = -this % n;
thisNegative = true;
}
else
tempNum = this % n; // ensures (tempNum * tempNum) < b^(2k)
if ((n.data[maxLength - 1] & 0x80000000) != 0) // negative n
n = -n;
// calculate constant = b^(2k) / m
BigInteger constant = new BigInteger();
int i = n.dataLength << 1;
constant.data[i] = 0x00000001;
constant.dataLength = i + 1;
constant = constant / n;
int totalBits = exp.bitCount();
int count = 0;
// perform squaring and multiply exponentiation
for (int pos = 0; pos < exp.dataLength; pos++)
{
uint mask = 0x01;
//Console.WriteLine("pos = " + pos);
for (int index = 0; index < 32; index++)
{
if ((exp.data[pos] & mask) != 0)
resultNum = BarrettReduction(resultNum * tempNum, n, constant);
mask <<= 1;
tempNum = BarrettReduction(tempNum * tempNum, n, constant);
if (tempNum.dataLength == 1 && tempNum.data[0] == 1)
{
if (thisNegative && (exp.data[0] & 0x1) != 0) //odd exp
return -resultNum;
return resultNum;
}
count++;
if (count == totalBits)
break;
}
}
if (thisNegative && (exp.data[0] & 0x1) != 0) //odd exp
return -resultNum;
return resultNum;
}
//***********************************************************************
// Fast calculation of modular reduction using Barrett's reduction.
// Requires x < b^(2k), where b is the base. In this case, base is
// 2^32 (uint).
//
// Reference [4]
//***********************************************************************
private BigInteger BarrettReduction(BigInteger x, BigInteger n, BigInteger constant)
{
int k = n.dataLength,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -