C# BigDecimal上的内存有效余数函数
背景: 不久前,我开始为空闲/增量游戏制作自己的BigDecimal实现,它不太关心精度,只关心范围。该类型基于BigInteger 它与其他BigDecimal实现类似。 得到尾数(BigInteger)和指数(int) 我已经实现了所有的基本操作和一些其他数学函数,以备需要。 问题是余数函数。 为了使函数返回正确的结果,我必须使用除法、乘法和减法的全精度,这意味着我必须将分子乘以10^指数(加零以获得精确的除法)问题是,当计算这样一个数字时,速度会很慢,而且最重要的是会影响内存,这对于依赖客户端机器的游戏来说是很好的,但问题是我正在为一个在线游戏制作它,服务器可以有1-2GB内存和许多并发玩家 我已经检查过我是否在游戏中使用过余数函数,没有,我从来没有使用过,所以如果它很慢也可以,因为我没有使用它,但是我想学习如何解决这样的问题 我用的方程式是: //余数=分子-商x分母 示例:C# BigDecimal上的内存有效余数函数,c#,biginteger,bigdecimal,bignum,arbitrary-precision,C#,Biginteger,Bigdecimal,Bignum,Arbitrary Precision,背景: 不久前,我开始为空闲/增量游戏制作自己的BigDecimal实现,它不太关心精度,只关心范围。该类型基于BigInteger 它与其他BigDecimal实现类似。 得到尾数(BigInteger)和指数(int) 我已经实现了所有的基本操作和一些其他数学函数,以备需要。 问题是余数函数。 为了使函数返回正确的结果,我必须使用除法、乘法和减法的全精度,这意味着我必须将分子乘以10^指数(加零以获得精确的除法)问题是,当计算这样一个数字时,速度会很慢,而且最重要的是会影响内存,这对于依赖客
value1 = 12500E20
value2 = 11300E0
result = value1 % value2
Expected result = 4200
Actual result = 53000E14
When full precision used (Slower) = 4200
public static HNumber Remainder(HNumber left, HNumber right)
{
//Remainder = Numerator - Quotient x Denominator
if (right.IsZero)
throw new DivideByZeroException("The Divisor is zero");
int digitDiff = left.Precision - (left.DigitCount - right.DigitCount);
digitDiff = Math.Max(0, digitDiff);
left.Mantissa *= BigInteger.Pow(10, digitDiff);
left.Truncate(left.DigitCount + digitDiff + left.Exponent);
BigInteger mantissa = BigInteger.Divide(tmpLeft.Mantissa, right.Mantissa);
int exponent = left.Exponent - right.Exponent - digitDiff;
HNumber quotient = new HNumber(mantissa, exponent);
HNumber qd = Multiply(quotient, right);
HNumber result = Subtract(left, qd);
return result;
}
代码:
value1 = 12500E20
value2 = 11300E0
result = value1 % value2
Expected result = 4200
Actual result = 53000E14
When full precision used (Slower) = 4200
public static HNumber Remainder(HNumber left, HNumber right)
{
//Remainder = Numerator - Quotient x Denominator
if (right.IsZero)
throw new DivideByZeroException("The Divisor is zero");
int digitDiff = left.Precision - (left.DigitCount - right.DigitCount);
digitDiff = Math.Max(0, digitDiff);
left.Mantissa *= BigInteger.Pow(10, digitDiff);
left.Truncate(left.DigitCount + digitDiff + left.Exponent);
BigInteger mantissa = BigInteger.Divide(tmpLeft.Mantissa, right.Mantissa);
int exponent = left.Exponent - right.Exponent - digitDiff;
HNumber quotient = new HNumber(mantissa, exponent);
HNumber qd = Multiply(quotient, right);
HNumber result = Subtract(left, qd);
return result;
}
这段代码可以工作并给出准确的结果,但正如我前面所说的,它的速度慢(与其他函数相比),而且内存效率不高
GitHub上的完整代码:
(有点乱,对不起)
最后的问题是,有没有其他方法可以不用left.Truncate(left.DigitCount+digitDiff+left.Exponent)实现它?使用大整数。如果需要十进制值,则乘以分子,并以10的相同幂表示。完成后,将结果除以相同的十次方。