Число изменяется при преобразовании Double в Numerics.BigInteger - PullRequest
0 голосов
/ 29 февраля 2012
using System.Numerics;

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

Почему значение BigInteger - это не 1 килограмм (1000 с последующим пакетом 0)?

Ответы [ 2 ]

4 голосов
/ 29 февраля 2012

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

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

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

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

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

BigInteger bigBase = BigInteger.Pow(1000, 99);
1 голос
/ 29 февраля 2012

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

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

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

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

 var bigBase = (BigInteger)doubleNumber;

Эквивалентно:

var bigBase = new BigInteger(doubleNumber);
...