📄 biginteger.cs
字号:
// take the absolute value of the inputs
try
{
if((bi1.data[lastPos] & 0x80000000) != 0) // bi1 negative
{
bi1Neg = true; bi1 = -bi1;
}
if((bi2.data[lastPos] & 0x80000000) != 0) // bi2 negative
{
bi2Neg = true; bi2 = -bi2;
}
}
catch(Exception) {}
BigInteger result = new BigInteger();
// multiply the absolute values
try
{
for(int i = 0; i < bi1.dataLength; i++)
{
if(bi1.data[i] == 0) continue;
ulong mcarry = 0;
for(int j = 0, k = i; j < bi2.dataLength; j++, k++)
{
// k = i + j
ulong val = ((ulong)bi1.data[i] * (ulong)bi2.data[j]) +
(ulong)result.data[k] + mcarry;
result.data[k] = (uint)(val & 0xFFFFFFFF);
mcarry = (val >> 32);
}
if(mcarry != 0)
result.data[i+bi2.dataLength] = (uint)mcarry;
}
}
catch(Exception)
{
throw(new ArithmeticException("Multiplication overflow."));
}
result.dataLength = bi1.dataLength + bi2.dataLength;
if(result.dataLength > maxLength)
result.dataLength = maxLength;
while(result.dataLength > 1 && result.data[result.dataLength-1] == 0)
result.dataLength--;
// overflow check (result is -ve)
if((result.data[lastPos] & 0x80000000) != 0)
{
if(bi1Neg != bi2Neg && result.data[lastPos] == 0x80000000) // different sign
{
// handle the special case where multiplication produces
// a max negative number in 2's complement.
if(result.dataLength == 1)
return result;
else
{
bool isMaxNeg = true;
for(int i = 0; i < result.dataLength - 1 && isMaxNeg; i++)
{
if(result.data[i] != 0)
isMaxNeg = false;
}
if(isMaxNeg)
return result;
}
}
throw(new ArithmeticException("Multiplication overflow."));
}
// if input has different signs, then result is -ve
if(bi1Neg != bi2Neg)
return -result;
return result;
}
//***********************************************************************
// Overloading of unary << operators
//***********************************************************************
public static BigInteger operator <<(BigInteger bi1, int shiftVal)
{
BigInteger result = new BigInteger(bi1);
result.dataLength = shiftLeft(result.data, shiftVal);
return result;
}
// least significant bits at lower part of buffer
private static int shiftLeft(uint[] buffer, int shiftVal)
{
int shiftAmount = 32;
int bufLen = buffer.Length;
while(bufLen > 1 && buffer[bufLen-1] == 0)
bufLen--;
for(int count = shiftVal; count > 0;)
{
if(count < shiftAmount)
shiftAmount = count;
//Console.WriteLine("shiftAmount = {0}", shiftAmount);
ulong carry = 0;
for(int i = 0; i < bufLen; i++)
{
ulong val = ((ulong)buffer[i]) << shiftAmount;
val |= carry;
buffer[i] = (uint)(val & 0xFFFFFFFF);
carry = val >> 32;
}
if(carry != 0)
{
if(bufLen + 1 <= buffer.Length)
{
buffer[bufLen] = (uint)carry;
bufLen++;
}
}
count -= shiftAmount;
}
return bufLen;
}
//***********************************************************************
// Overloading of unary >> operators
//***********************************************************************
public static BigInteger operator >>(BigInteger bi1, int shiftVal)
{
BigInteger result = new BigInteger(bi1);
result.dataLength = shiftRight(result.data, shiftVal);
if((bi1.data[maxLength-1] & 0x80000000) != 0) // negative
{
for(int i = maxLength - 1; i >= result.dataLength; i--)
result.data[i] = 0xFFFFFFFF;
uint mask = 0x80000000;
for(int i = 0; i < 32; i++)
{
if((result.data[result.dataLength-1] & mask) != 0)
break;
result.data[result.dataLength-1] |= mask;
mask >>= 1;
}
result.dataLength = maxLength;
}
return result;
}
private static int shiftRight(uint[] buffer, int shiftVal)
{
int shiftAmount = 32;
int invShift = 0;
int bufLen = buffer.Length;
while(bufLen > 1 && buffer[bufLen-1] == 0)
bufLen--;
//Console.WriteLine("bufLen = " + bufLen + " buffer.Length = " + buffer.Length);
for(int count = shiftVal; count > 0;)
{
if(count < shiftAmount)
{
shiftAmount = count;
invShift = 32 - shiftAmount;
}
//Console.WriteLine("shiftAmount = {0}", shiftAmount);
ulong carry = 0;
for(int i = bufLen - 1; i >= 0; i--)
{
ulong val = ((ulong)buffer[i]) >> shiftAmount;
val |= carry;
carry = ((ulong)buffer[i]) << invShift;
buffer[i] = (uint)(val);
}
count -= shiftAmount;
}
while(bufLen > 1 && buffer[bufLen-1] == 0)
bufLen--;
return bufLen;
}
//***********************************************************************
// Overloading of the NOT operator (1's complement)
//***********************************************************************
public static BigInteger operator ~(BigInteger bi1)
{
BigInteger result = new BigInteger(bi1);
for(int i = 0; i < maxLength; i++)
result.data[i] = (uint)(~(bi1.data[i]));
result.dataLength = maxLength;
while(result.dataLength > 1 && result.data[result.dataLength-1] == 0)
result.dataLength--;
return result;
}
//***********************************************************************
// Overloading of the NEGATE operator (2's complement)
//***********************************************************************
public static BigInteger operator -(BigInteger bi1)
{
// handle neg of zero separately since it'll cause an overflow
// if we proceed.
if(bi1.dataLength == 1 && bi1.data[0] == 0)
return (new BigInteger());
BigInteger result = new BigInteger(bi1);
// 1's complement
for(int i = 0; i < maxLength; i++)
result.data[i] = (uint)(~(bi1.data[i]));
// add one to result of 1's complement
long val, carry = 1;
int index = 0;
while(carry != 0 && index < maxLength)
{
val = (long)(result.data[index]);
val++;
result.data[index] = (uint)(val & 0xFFFFFFFF);
carry = val >> 32;
index++;
}
if((bi1.data[maxLength-1] & 0x80000000) == (result.data[maxLength-1] & 0x80000000))
throw (new ArithmeticException("Overflow in negation.\n"));
result.dataLength = maxLength;
while(result.dataLength > 1 && result.data[result.dataLength-1] == 0)
result.dataLength--;
return result;
}
//***********************************************************************
// Overloading of equality operator
//***********************************************************************
public static bool operator ==(BigInteger bi1, BigInteger bi2)
{
if(Object.Equals(bi1, bi2))
return true;
else
return bi1.Equals(bi2);
}
public static bool operator !=(BigInteger bi1, BigInteger bi2)
{
if(Object.Equals(bi1, bi2))
return false;
else
return !(bi1.Equals(bi2));
}
public override bool Equals(object o)
{
if(o==null || !(o is BigInteger)) return false;
BigInteger bi = (BigInteger)o;
if(this.dataLength != bi.dataLength)
return false;
for(int i = 0; i < this.dataLength; i++)
{
if(this.data[i] != bi.data[i])
return false;
}
return true;
}
public override int GetHashCode()
{
return this.ToString().GetHashCode();
}
//***********************************************************************
// Overloading of inequality operator
//***********************************************************************
public static bool operator >(BigInteger bi1, BigInteger bi2)
{
int pos = maxLength - 1;
// bi1 is negative, bi2 is positive
if((bi1.data[pos] & 0x80000000) != 0 && (bi2.data[pos] & 0x80000000) == 0)
return false;
// bi1 is positive, bi2 is negative
else if((bi1.data[pos] & 0x80000000) == 0 && (bi2.data[pos] & 0x80000000) != 0)
return true;
// same sign
int len = (bi1.dataLength > bi2.dataLength) ? bi1.dataLength : bi2.dataLength;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -