C# 将一个大整数除以以返回double

C# 将一个大整数除以以返回double,c#,.net,biginteger,division,C#,.net,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)); } } 我

我想计算直线的斜率

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函数,它返回除法结果加上余数,但不知道如何应用它来获得double。我处理的数字远远超出了Int64.MaxValue的范围,因此余数本身可能超出了常规除法计算的范围

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


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

这不涉及负数,但希望能给你一个开始

        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);
            }
        }
double doubleMax=double.MaxValue;
大整数分子=120;
大整数分母=50;
if(分母!=0)
{
Debug.WriteLine(分子/分母);
Debug.WriteLine(分子%分母);
BigInteger ansI=分子/分母;
如果(ansI<(int)doubleMax)
{
双斜率=(双)ansI+((双)(分子%分母)/(双)分母);
调试写线(斜率);
}
}
库中有一个到double的转换运算符

另外,记住返回无穷大作为垂直线的特例,您将在当前代码中得到一个除零异常。可能最好先计算X1-X2,如果为零则返回无穷大,然后进行除法,以避免冗余操作。

从Codeplex获取。它是微软的一部分,所以它是.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分钟

关于我所做的唯一重大修改是在结果为正或负零/无穷大时如何设置结果的符号。当我使用它时,我为您将其转换为
biginger
扩展方法:

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

}
公共静态类BigIntExtensions
{
公共静态双除法和返回双除法(此大整数x,大整数y)
{
//双值类型表示一个双精度64位数字,带有
//数值范围为-1.79769313486232e308至+1.79769313486232e308
//不适合此范围的值返回为+/-无穷大
if(安全广播双倍(x)和安全广播双倍(y))
{
返回(双)x/(双)y;
}
//老调重弹,找出结果的标志
bool isNegativeResult=((x.Sign<0和y.Sign>0)| |(x.Sign>0和y.Sign<0));
//缩放分子以通过整数除法表示分数部分
BigInteger非规范化=(x*s\bnDoublePrecision)/y;
if(非规范化的.IsZero)
{
返回isNegativeResult?BitConverter.Int64BitsToDouble(未选中((长)0x80000000000000)):0d;//下溢到-+0
}
双结果=0;
bool isDouble=false;
int scale=DoubleMaxScale;
而(比例>0)
{
如果(!isDouble)
{
if(安全卡斯托双重(非规范化))
{
结果=(双重)非规范化;
isDouble=true;
}
其他的
{
非规范化=非规范化/10;
}
}
结果=结果/10;
比例--;
}
如果(!isDouble)
{
return isNegativeResult?Double.NegativeInfinity:Double.PositiveInfinity;
}
其他的
{
返回结果;
}
}
私有常量int DoubleMaxScale=308;
私有静态只读BigInteger s_bnDoublePrecision=BigInteger.Pow(10,DoubleMaxScale);
私有静态只读BigInteger s_bnDoubleMaxValue=(BigInteger)Double.MaxValue;
私有静态只读BigInteger SbNdoubleMinValue=(BigInteger)Double.MinValue;
私有静态bool SafeCastToDouble(BigInteger值)
{

返回SbNdoubleMinValue需要多精确?您要处理的数字是什么..请显示numbers@AustinSalonen:精度越高越好,但即使是几个小数位数的精度也足以达到我的要求。@DJKRAZE:我正在处理以百万为基数的数字10数字。也许这会有所帮助?谢谢。但是,这只有在整数结果在Int32或UInt64范围内时才有效。请考虑将N除以3,其中N有10000000个数字。@RaheelKhan正是如此。请阅读问题public double CalculateSlope。如果大于double,则答案不能转换为double。当然。斜率本身总是在-1.0和1.0之间。精度损失很大。@RaheelKhan没有什么可以限制斜率。1/0=无穷大。斜率
1/0
0/1
是可以在分区之外处理的罕见转角情况。这就是为什么我指定了可接受斜率的范围,即。-1.0到1.0。有趣。这个类在.NET 4中不存在,是吗?如果它是测试版或候选版本,那么很遗憾我不能在生产代码中使用它。它是测试版。为什么不能使用它?这是用于生产应用程序。质量保证不允许使用测试库。谢谢。不幸的是,我不能在生产代码中使用BigRational因为它是beta版。论坛和书籍应该是答案。@RaheelKhan:或者你可以从BigR中去掉显式转换操作符