C#中的BigInteger部门

时间:2012-08-08 06:50:30

标签: c# .net biginteger division

我正在编写一个需要在C#中精确划分BigInteger类的类。

示例:

BigInteger x = BigInteger.Parse("1000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
BigInteger y = BigInteger.Parse("2000000000000000000000000000000000000000000000000000000000000000000000000000000000000");

x /= y;

Console.WriteLine(x.ToString());

//Output = 0

问题是作为一个整数,自然它不包含十进制值。 如何克服这一点以获得0.5的实际结果(给出示例)。

P.S。解决方案必须能够准确地划分任何BigInteger,而不仅仅是示例!

8 个答案:

答案 0 :(得分:15)

在上面的例子中,数字仍然很小,可以转换为double,所以在这种情况下你可以说

double result = (double)x / (double)y;

如果xy对于double来说太大了但仍具有可比性,那么这个很棒的技巧可能会有所帮助:

double result = Math.Exp(BigInteger.Log(x) - BigInteger.Log(y));

但总的来说,当BigInteger很大,而且它们的商数也很大时,如果不导入第三方库,这很难做到。

答案 1 :(得分:6)

分部需要什么准确度?一种方法是:

  • 将分子乘以比如1000
  • 除以数字
  • 将结果转换为double并除以1000

代码相同:

BigInteger x = BigInteger.Parse("1000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
BigInteger y = BigInteger.Parse("2000000000000000000000000000000000000000000000000000000000000000000000000000000000000");

x *= 1000;
x /= y;
double result = (double)x;
result /= 1000;
Console.WriteLine(result);

答案 2 :(得分:1)

如果需要保持完全精确,请使用有理数的实现(Java等效项将是Apache Commons Math库中的Fraction类)。有各种各样的实现潜伏,但.NET 4.0的最轻量级解决方案(因为它内置了System.Numerics.BigInteger)将是以下内容:

        System.Numerics.BigInteger x = System.Numerics.BigInteger.Parse("10000000000000000000000000000000000000000000000000000");

        System.Numerics.BigInteger y = System.Numerics.BigInteger.Parse("20000000000000000000000000000000000000000000000000000");

        // From BigRationalLibrary
        Numerics.BigRational r = new Numerics.BigRational(x,y);

        Console.Out.WriteLine(r.ToString());
        // outputs "1/2", but can be converted to floating point if needed.

要使其工作,您需要来自.Net 4.0 System.Numerics.dll的System.Numberics.BigInteger和CodePlex的BigRational实现。

Rational structure也实施了Microsoft Solver Foundation 3.0。在撰写本文时,www.solverfoundation.com网站被破坏,因此链接到存档。

答案 3 :(得分:0)

你可能知道整数除法不会产生十进制值,所以你的结果被截断为0.根据this question可以找到大的双重实现here,但它的最后一个版本是在2009年如果你看得更远,你可能会找到更新的或者这个简单完成。

答案 4 :(得分:0)

听起来像Fixed Point的工作(而不是浮点)。

只需将分子预先移位所需的小数位数,如下所示:

BigInteger quotient = (x << 10) / y;

这将在点之后给出10位(大约3位小数)。

答案 5 :(得分:0)

//b = 10x bigger as a => fraction should be 0.1
BigInteger a = BigInteger.Pow(10, 5000);
BigInteger b = BigInteger.Pow(10, 5001);

//before the division, multiple by a 1000 for a precision of 3, afterwards 
//divide the result by this.
var fraction = (double) BigInteger.Divide(a * 1000, b) / 1000;

答案 6 :(得分:0)

我找到了一个纯BigInteger版本:

static BigInteger FlooredIntDiv(BigInteger a, BigInteger b)
{
    if (a < 0)
    {
        if (b > 0)
            return (a - b + 1) / b;
    }
    else if (a > 0)
    {
        if (b < 0)
            return (a - b - 1) / b;
    }
    return a / b;
}

源(用于长型): Floored integer division

答案 7 :(得分:-1)

解析它加倍:

double a = Convert.ToDouble(x);
double b = Convert.ToDouble(y);

Console.WriteLine(a / b);