JohnB
JohnB

Reputation: 19002

Number changes when converting Double to Numerics.BigInteger

using System.Numerics;

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

Why is the BigInteger value not just 1 kagillion (1,000 followed by a bagillion 0's)?

Upvotes: 0

Views: 432

Answers (2)

Lasse V. Karlsen
Lasse V. Karlsen

Reputation: 391476

System.Double only has 15 decimal digits of precision, which means the value will be close to the actual value, but might not be precise.

It all has to do with how floating point values are encoded in order to occupy a fixed amount of memory.

This is exactly the same problem which lets 1.0 end up as 0.999999999999999999etc.

If you need absolute precision, you need to use a library/type which has that, double has not.

For your specific code, you might want to do this:

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

Upvotes: 4

Makotosan
Makotosan

Reputation: 1149

The implementation of BigInteger uses a lot of bit shifting, so when you convert a double to a BigInteger, the double representation has a finite set of bits (64 bits in for a double), so not all the bits are there to accurately represent the value.

Instead of using Math.Pow, you should be using

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

Also, explicitly casting a numeric type to a BigInteger is the same as using the BigInteger constructor:

 var bigBase = (BigInteger)doubleNumber;

Is equivalent to:

var bigBase = new BigInteger(doubleNumber);

Upvotes: 1

Related Questions