C# 当BigInteger的大小超过¼时,BigInteger的对数错误;千兆字节

C# 当BigInteger的大小超过¼时,BigInteger的对数错误;千兆字节,c#,.net,biginteger,logarithm,base-class-library,C#,.net,Biginteger,Logarithm,Base Class Library,当我有一个biginger的大小超过2千兆位(即¼千兆字节;我通过反复试验找到了这个阈值)时,对数方法给出了错误的答案。这段简单的代码说明: 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.W

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

  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
的数字,必须有一个零对数;对于
0
1
之间的数字,必须有一个负对数(没有整数)。我上面的数字
i1
i2
大于
1
,因为按照惯例,当最高有效字节介于
0
127
之间时,这意味着正
biginger

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

那么为什么这不起作用呢

PS!大于
2^^31
位的大小意味着
BigInteger
的实际值大于
2^(2^^31)
,或大约
约为8.8E+646456992



更新:我已发送到Microsoft Connect。阅读讨论后,我还意识到,由于
biginger
的设计和单个对象大小的上限为2G字节,因此
biginger
永远不会超过2G字节(无论您有多少内存)。因此,当
biginether
介于¼和2G字节之间时,就会发生此错误。

让我猜一下:该值为

-1.3134912384757032e9
(计算对数时的模小变化)

最高设定位的索引存储并以
int
传递,以及

8*300000000 = 2400000000 > 2147483647
-1894967296 * log 2 = -1.3134912384757032e9
因此,索引被压缩为一个负数,即
-1894967296
,并且

8*300000000 = 2400000000 > 2147483647
-1894967296 * log 2 = -1.3134912384757032e9

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

32位或64位体系结构?这是否回答了您的问题?或者是相关的?@Pete发现得不错,但我认为这就是为什么他要初始化一个额外的字节。除非字节数组需要以一个字符结尾,以某种方式使1成为符号字符。@Jeppe Stig Nielsen你能告诉我们log2的输出实际上是什么吗,或者每次都不同吗?@glace:当我测试它时,它似乎是可靠的
-1313491238.4757
。实际上我认为这是设计的。你必须习惯。但是,如果确实使用长索引重载的
Array.CreateInstance
,则会由于以下原因得到
OutOfMemoryException
。因此,OP创建的数组实际上一开始甚至不是
300000001
元素,但它只是超出该限制的位数。这个数组只占用约300MB的空间,这应该不是什么问题。我敢打赌,内部正在发生某种中间现象,即生成一个太大的对象。我的机器上有6GB的空闲内存,所以它似乎应该工作。我想这个答案解释了发生了什么。我正在考虑提交那个bug报告。该值是您引用的值(在我的示例中,该值被格式化为不带
e9
符号的字符串,但您得到了正确的数字)。@mellamokb数组是3亿个元素和1个元素(每个元素是一个字节)。所以它超过2G,但不超过2G(有这个系数8,这就是为什么我写了¼GB)。但是如果内部使用的数组(由
biginger
使用)被限制为2G字节,那么这就设置了
biginger
可以变成多大的有效限制,并且我超过了该级别的八分之一(如果存在)。