【发布时间】:2013-01-18 16:08:31
【问题描述】:
当我的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,我们必须有一个零对数,对于介于0 和1 之间的数字,我们必须有一个负对数(没有整数)。我上面的数字i1 和i2 大于1,因为按照惯例,当最高有效字节在0 和127 之间时,这意味着正BigInteger。
现在,如果您阅读 BigInteger.Log 的文档,他们声称如果对数“超出 Double 数据类型的范围”,它可能会抛出。现在,显然这需要一台内存存储量超过1E+300 字节的计算机,而可观测宇宙太小而无法容纳这样一台计算机,所以我想这永远不会发生。
那么为什么这不起作用呢?
PS!大小超过2 ^^ 31 位意味着BigInteger 的实际值超过2 ^^ (2 ^^ 31),或近似为circa 8.8E+646456992。
更新:我向 Microsoft Connect 发送了 a bug report。阅读讨论后,我也意识到由于BigInteger 的设计和单个对象大小的上限为 2 GB,BigInteger 永远不会超过 2 GB(无论有多少内存你有)。因此,当BigInteher 介于 ¼ 和 2 GB 之间时,就会发生此错误。
【问题讨论】:
-
32 位还是 64 位架构?
-
这能回答你的问题吗? stackoverflow.com/questions/12003719/log-of-a-very-large-number 或者可能相关?
-
@Pete 很好的发现,但我认为这就是他初始化一个额外字节的原因。除非字节数组需要以某种方式以 1 成为符号字符的方式终止。
-
@Jeppe Stig Nielsen 你能告诉我们 log2 的实际输出是什么,还是每次都不一样?
-
@glace:当我测试它时,它似乎是可靠的
-1313491238.4757。
标签: c# .net biginteger logarithm base-class-library