繁体   English   中英

C#中的BigInteger部门

[英]BigInteger division in C#

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

例:

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

x /= y;

Console.WriteLine(x.ToString());

//Output = 0

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

PS该解决方案必须能够准确地划分所有BigInteger,而不仅仅是示例!

在上面的示例中,数字仍然很小,可以转换为double ,因此在这种情况下,您可以说

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

如果xy对于double y太大了,但仍然可比,那么这个好技巧可能会有所帮助:

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

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

您需要什么精度划分? 一种方法是:

  • 分子乘以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);

如果需要保持完全的精度,请使用合理性的实现(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实现。

Microsoft Solver Foundation 3.0中也实现了Rational结构 在撰写本文时,www.solverfoundation.com网站已损坏,因此指向档案的链接。

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

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

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

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

这将为您提供点后的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;

将其解析为两倍:

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