简体   繁体   English

C#中的BigInteger部门

[英]BigInteger division in C#

I am writing a class which needs accurate division of the BigInteger class in C#. 我正在编写一个需要在C#中精确划分BigInteger类的类。

Example: 例:

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

x /= y;

Console.WriteLine(x.ToString());

//Output = 0

The problem is that being an Integer, naturally it does not hold decimal values. 问题是作为整数,它自然不包含十进制值。 How can I overcome this to get the real result of 0.5 (given example). 我如何克服这个问题以获得0.5的真实结果(给出示例)。

PS The solution must be able to accurately divide any BigInteger, not just the example! PS该解决方案必须能够准确地划分所有BigInteger,而不仅仅是示例!

In the above example, the numbers are still small enough to be converted to double , so in this case you can say 在上面的示例中,数字仍然很小,可以转换为double ,因此在这种情况下,您可以说

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

If x and y are too huge for a double but still comparable, maybe this great trick is helpful: 如果xy对于double y太大了,但仍然可比,那么这个好技巧可能会有所帮助:

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

But in general, when the BigInteger are huge, and their quotient is huge too, this is hard to do without importing a third-party library. 但是总的来说,当BigInteger很大且它们的商也很大时,如果不导入第三方库就很难做到这一点。

What accuracy you need for the division? 您需要什么精度划分? One way would be: 一种方法是:

  • Multiply the numerator by, say, 1000 分子乘以1000
  • Divide the numbers 除数
  • Convert the result to double and divide by 1000 将结果转换为double并除以1000

The same in code: 代码相同:

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

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

If you need to keep full precision, use an implementation of rationals (the Java equivalent would be the Fraction class from Apache Commons Math library). 如果需要保持完全的精度,请使用合理性的实现(Java等效项是Apache Commons Math库中的Fraction类)。 There are various implementations lurking around, but the most light weight solution for .NET 4.0 (as it has System.Numerics.BigInteger built in) would be the following: 潜伏着各种各样的实现,但是.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.

To get this to work you need the System.Numberics.BigInteger from .Net 4.0 System.Numerics.dll and the BigRational implementation from CodePlex. 若要使其正常工作,您需要.Net 4.0 System.Numerics.dll中的System.Numberics.BigInteger和CodePlex中的BigRational实现。

There is a Rational structure implemented in the Microsoft Solver Foundation 3.0 too. Microsoft Solver Foundation 3.0中也实现了Rational结构 At the time of writing, the www.solverfoundation.com site was broken, thus a link to the archive. 在撰写本文时,www.solverfoundation.com网站已损坏,因此指向档案的链接。

您可能知道整数除法将不会产生十进制值,因此您的结果将被截断为0。根据此问题,可以在此处找到大的double实现,但上次发布是在2009年。或仅此一项就完成了。

Sound like a job for Fixed Point (rather than floating point). 听起来像是定点 (而不是浮点)的工作。

Simply pre-shift the numerator by the number of fractional bits you need, like this: 只需将分子预先移位所需的小数位数,如下所示:

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

That would give you 10 bits after the dot (approximately 3 decimal digits). 这将为您提供点后的10位(大约3个十进制数字)。

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

Parse it to double: 将其解析为两倍:

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

Console.WriteLine(a / b);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM