Когда у меня есть BigInteger
, размер которого превышает 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
, это означает положительный BigInteger
.
Теперь, если вы прочитаете документацию для BigInteger.Log
, они утверждают, что она может бросить, если логарифм "выходит за пределы диапазона Double тип данных". Теперь, очевидно, для этого потребуется компьютер с памятью размером более 1E+300
байтов, а наблюдаемый юниверс слишком мал, чтобы содержать такой компьютер, поэтому я предполагаю, что этого никогда не произойдет.
Так почему же это не работает?
PS! Размер над битами 2 ^^ 31
означает, что фактическое значение BigInteger
превышает 2 ^^ (2 ^^ 31)
или приблизительно circa 8.8E+646456992
.
UPDATE: я отправил отчет об ошибке в Microsoft Connect. После ознакомления с обсуждениями я также осознал, что из-за дизайна BigInteger
и верхнего предела в 2 гигабайта для размера одного единственного объекта BigInteger
никогда не может превышать 2 гигабайта (независимо от того, сколько памяти у тебя есть). Следовательно, эта ошибка возникает, когда BigInteher
находится между ¼ и 2 гигабайтами.