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
可以变成多大的有效限制,并且我超过了该级别的八分之一(如果存在)。