划分BigIntegers返回double

我想计算一条线的斜率。

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)); } } 

我知道BigInteger有一个DivRem函数,它返回除法结果和余数,但我不知道如何应用它来获得双精度。 我正在处理的数字远远超出了Int64.MaxValue的范围,因此剩余部分本身可能超出了传统划分的范围。

编辑 :不确定它是否有帮助,但我只处理正整数(> = 1)。

重要提示 :我只需要几个小数点的精度(5应该足够我的目的)。

BigRational库有一个转换运算符可以加倍。

另外,请记住将无穷大作为垂直线的特殊情况返回,您将使用当前代码获得除零exception。 可能最好先计算X1 – X2,如果它为零则返回无穷大,然后进行除法,以避免冗余操作。

从Codeplex获取BigRational 。 它是微软基类库的一部分,因此它是.Net的一项正在进行的工作。 一旦你有了,那么做一些像:

 System.Numerics.BigInteger x = GetDividend() ; System.Numerics.BigInteger y = GetDivisor() ; BigRational r = new BigRational( x , y ) ; double value = (double) r ; 

当然,处理不可避免的溢出/下溢/精度损失是另一个问题。

既然你不能将BigRational库放入你的代码中,显然,另一种方法是找出正确的算法书并推出你自己的…

当然,这里简单的方法是“滚动自己”,因为有理数表示为两个整数的比率(除法),就是从BigRational类中获取显式转换为double运算符并调整它以适应。 我花了大约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; } } 

这不是负面的,但希望能给你一个开始。

  double doubleMax = double.MaxValue; BigInteger numerator = 120; BigInteger denominator = 50; if (denominator != 0) { Debug.WriteLine(numerator / denominator); Debug.WriteLine(numerator % denominator); BigInteger ansI = numerator / denominator; if (ansI < (int)doubleMax) { double slope = (double)ansI + ((double)(numerator % denominator) / (double)denominator); ; Debug.WriteLine(slope); } }