c# - 将 BigIntegers 相除以返回 double

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

我知道 BigInteger 有一个 DivRem 函数,它返回除法结果加上余数,但我不确定如何应用它来获得 double 。我正在处理的数字远远超出了 Int64.MaxValue 的范围,因此余数本身可能超出了传统除法计算的范围。

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

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

最佳答案

获取BigRational来自 Codeplex。它是 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 ;

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

由于您不能将 BigRational 库放入您的代码中,显然,另一种方法是取出 right algorithms book并滚动你自己的...

当然,这里“滚动自己”的简单方法,因为有理数表示为两个整数的比率(除法),是从 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;
  }

}

关于c# - 将 BigIntegers 相除以返回 double,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11872311/

相关文章:

java - 如何在Reducer中导入BigInteger Writable?

c# - 使用联合安全保护服务器应用程序之间的 WCF 服务调用

c# - C#: Call a method every 5 minutes from a foreach loop

c# - 不同线程访问 MemoryStream

.net - 托管 C++ 中的泛型泛型

java - 我在执行解密时遇到基数超出范围异常

Java:ByteArray 到正数,反之亦然

c# - 如何从其基类的实例创建新对象?

c# - 错误 MCG0004 :InternalAssert Assert Failed when building UWP app in release mode

c# - 如何从 C# 提交 multipart/form-data HTTP POST 请求