Rah*_*han 7 .net c# biginteger division
我想计算一条线的斜率.
public sealed class Point
{
public System.Numerics.BigInteger x = 0;
public System.Numerics.BigInteger y = 0;
public double CalculateSlope (Point point)
{
return ((point.Y - this.Y) / (point.X - this.X));
}
}
Run Code Online (Sandbox Code Playgroud)
我知道BigInteger有一个DivRem函数可以返回除法结果加上余数,但我不知道如何应用它来得到一个double.我正在处理的数字远远超出了Int64.MaxValue的范围,因此剩余部分本身可能超出了传统划分的范围.
编辑:不确定它是否有帮助,但我只处理正整数(> = 1).
重要提示:我只需要几个小数点的精度(5应该足够我的目的).
从 Codeplex获取BigRational。它是 Microsoft 的Base Class Library 的一部分,因此它是 .Net 的一项正在进行的工作。一旦你有了它,然后做这样的事情:
System.Numerics.BigInteger x = GetDividend() ;
System.Numerics.BigInteger y = GetDivisor() ;
BigRational r = new BigRational( x , y ) ;
double value = (double) r ;
Run Code Online (Sandbox Code Playgroud)
处理不可避免的上溢/下溢/精度损失当然是另一个问题。
由于您不能将 BigRational 库放入您的代码中,显然,另一种方法是拿出正确的算法书并推出您自己的......
当然,这里“滚动自己的”的简单方法,因为有理数表示为两个整数的比率(除法),是从 BigRational 类中获取显式转换为双运算符并对其进行调整以适应。我花了大约 15 分钟。
我所做的唯一重要修改是当结果为正或负零/无穷大时如何设置结果的符号。当我在做的时候,我把它转换成一个BigInteger扩展方法给你:
public static class BigIntExtensions
{
public static double DivideAndReturnDouble( this BigInteger x , BigInteger y )
{
// The Double value type represents a double-precision 64-bit number with
// values ranging from -1.79769313486232e308 to +1.79769313486232e308
// values that do not fit into this range are returned as +/-Infinity
if (SafeCastToDouble(x) && SafeCastToDouble(y))
{
return (Double) x / (Double) y;
}
// kick it old-school and figure out the sign of the result
bool isNegativeResult = ( ( x.Sign < 0 && y.Sign > 0 ) || ( x.Sign > 0 && y.Sign < 0 ) ) ;
// scale the numerator to preseve the fraction part through the integer division
BigInteger denormalized = (x * s_bnDoublePrecision) / y ;
if ( denormalized.IsZero )
{
return isNegativeResult ? BitConverter.Int64BitsToDouble(unchecked((long)0x8000000000000000)) : 0d; // underflow to -+0
}
Double result = 0 ;
bool isDouble = false ;
int scale = DoubleMaxScale ;
while ( scale > 0 )
{
if (!isDouble)
{
if ( SafeCastToDouble(denormalized) )
{
result = (Double) denormalized;
isDouble = true;
}
else
{
denormalized = denormalized / 10 ;
}
}
result = result / 10 ;
scale-- ;
}
if (!isDouble)
{
return isNegativeResult ? Double.NegativeInfinity : Double.PositiveInfinity;
}
else
{
return result;
}
}
private const int DoubleMaxScale = 308 ;
private static readonly BigInteger s_bnDoublePrecision = BigInteger.Pow( 10 , DoubleMaxScale ) ;
private static readonly BigInteger s_bnDoubleMaxValue = (BigInteger) Double.MaxValue;
private static readonly BigInteger s_bnDoubleMinValue = (BigInteger) Double.MinValue;
private static bool SafeCastToDouble(BigInteger value)
{
return s_bnDoubleMinValue <= value && value <= s_bnDoubleMaxValue;
}
}
Run Code Online (Sandbox Code Playgroud)
该BigRational库有一个转换操作符将翻一番.
另外,请记住将无穷大作为垂直线的特殊情况返回,您将使用当前代码获得除零异常.可能最好先计算X1 - X2,如果它为零则返回无穷大,然后进行除法,以避免冗余操作.