12

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

例子:

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

x /= y;

Console.WriteLine(x.ToString());

//Output = 0

问题是作为一个整数,它自然不包含十进制值。我怎样才能克服这个以获得 0.5 的实际结果(给定示例)。

PS 解必须能准确除任何BigInteger,不只是例子!

4

7 回答 7

17

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

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

如果xy对于 a 来说太大double但仍然具有可比性,也许这个绝妙的技巧会有所帮助:

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

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

于 2012-08-08T07:03:20.150 回答
7

除法需要什么精度?一种方法是:

  • 将分子乘以 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);
于 2012-08-08T06:56:41.717 回答
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实现。

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

于 2012-08-08T07:05:26.703 回答
0

您可能知道整数除法不会产生十进制值,因此您的结果将被截断为 0。根据这个问题,可以在此处找到大双精度实现,但它的最后一个版本是在 2009 年。如果您进一步看,您可能会发现更新的或者这个简单地完成了。

于 2012-08-08T06:57:41.957 回答
0

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

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

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

这会给你点后的 10 位(大约 3 个十进制数字)。

于 2012-08-08T07:17:19.297 回答
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;
于 2018-01-19T15:02:35.347 回答
-1

将其解析为双倍:

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

Console.WriteLine(a / b);
于 2012-08-08T06:54:41.910 回答