2012-02-28 2 views
0
using System.Numerics; 

double doubleNumber = Math.Pow(1000, 99); // = 1.0E+297 
BigInteger bigBase = (BigInteger)bigNumber; // = 1000000000000000017652801462756379714374878780719864776839443139119744823869255243069012222883470359078822072829219411228534934402712624705615450492327979456500795456339201761949451160807447294527656222743617592048849967890105831362861792425329827928397252374398383022243308510390698430058459037696 

Почему значение BigInteger не только 1 kagillion (1000 следует bagillion 0 ')?Номер изменяется при преобразовании Double в Numerics.BigInteger

+1

А, двойная арифметика. –

+0

Ха-ха, я только что узнал несколько новых слов: kagillion и bagillion! –

ответ

1

Реализация BigInteger использует много битового сдвига, поэтому при преобразовании двойной в BigInteger, двойное представление имеет конечное набор бит (бит 64 бит для двойного), поэтому не все биты должны точно представлять значение.

Вместо использования Math.pow, вы должны использовать

var bigBase = BigInteger.Pow(1000, 99); 

Кроме того, в явном виде отливки числового типа к BigInteger так же, как с помощью конструктора BigInteger:

var bigBase = (BigInteger)doubleNumber; 

равносилен до:

var bigBase = new BigInteger(doubleNumber); 
+0

СПАСИБО! (Еще 8) – JohnB

+0

'double' Спасибо! – JohnB

+0

Имхо этот ответ неправильный. Это не имеет ничего общего с битовым сдвигом в BigInteger, но с представлением с плавающей запятой 'Math.Pow (1000, 99)' это ** не ** '1.0E + 297', но одно из ближайших представимых значений в представлении fp , – soc

4

System.Double имеет только 15 десятичных цифр точности, что означает значение будет близко к фактической стоимости, но не может быть точным.

Все это связано с тем, как значения с плавающей запятой закодированы, чтобы занять фиксированный объем памяти.

Это точно такая же проблема, которая позволяет 1.0 заканчиваться как 0.999999999999999999etc.

Если вам нужна абсолютная точность, вам нужно использовать библиотеку/тип, который имеет то, что double не имеет.

Для вашего конкретного кода, вы можете сделать это:

BigInteger bigBase = BigInteger.Pow(1000, 99); 
+0

Спасибо. Есть ли более точная версия функции 'double Math.Pow()'? – JohnB

+0

Ну, да, есть [BigInteger.Pow] (http://msdn.microsoft.com/en-us/library/system.numerics.biginteger.pow.aspx). Я отредактировал ответ, чтобы отразить это. –

Смежные вопросы