11

当我有一个BigInteger大小超过 2 GB(即 ¼ GB;我通过反复试验找到这个阈值)时,对数方法给出了错误的答案。这个简单的代码说明了:

  byte[] bb;

  bb = new byte[150000001];
  bb[150000000] = 1;  // sets most significant byte to one
  var i1 = new BigInteger(bb);
  double log1 = BigInteger.Log(i1);
  Console.WriteLine(log1);   // OK, writes 831776616.671934

  bb = new byte[300000001];
  bb[300000000] = 1;  // sets most significant byte to one
  var i2 = new BigInteger(bb);
  double log2 = BigInteger.Log(i2);
  Console.WriteLine(log2);   // Broken, gives negative number, should be twice 831776616.671934

当然,对于超过 的数字1,我们必须有一个正对数,对于数字 ,我们必须有一个零对数1,对于介于0and之间的数字,我们必须有一个负对数1(那里没有整数)。我的数字i1i2以上的数字大于,1因为按照惯例,当最高有效字节介于0and之间时127,这意味着 positive BigInteger

现在,如果您阅读 的文档BigInteger.Log,他们声称如果对数“超出 Double 数据类型的范围”,它可能会抛出。现在,显然这需要一台内存容量超过1E+300字节的计算机,而可观测的宇宙太小而无法容纳这样的计算机,所以我想这永远不会发生。

那么为什么这不起作用呢?

PS!Size over 2 ^^ 31bits 表示 的实际值BigInteger超过2 ^^ (2 ^^ 31)或近似circa 8.8E+646456992


更新:我向 Microsoft Connect发送了错误报告。在阅读了讨论后,我也意识到,由于BigInteger单个对象大小的设计和上限为 2 GB,aBigInteger永远不会超过 2 GB(无论您有多少内存)。因此,当BigInteher¼ 和 2 GB 之间时,就会发生此错误。

4

1 回答 1

11

让我猜猜:价值是

-1.3134912384757032e9

(计算对数时取模小的变化)?

最高设置位的索引被存储并传入一个int, 和

8*300000000 = 2400000000 > 2147483647

因此索引环绕为负数,即-1894967296

-1894967296 * log 2 = -1.3134912384757032e9

哎呀。有人应该提交错误报告。

于 2013-01-18T17:09:43.690 回答