Reputation: 267
Consider following:
double x = 87974894654657d;
double y = 76216354532345d;
double a = x * y;
Console.WriteLine(a.ToString("n0"));
BigInteger x1 = new BigInteger(87974894654657);
BigInteger y1 = new BigInteger(76216354532345);
BigInteger a1 = x1 * y1;
Console.WriteLine(a1.ToString("n0"));
Output:
6.705.125.760.945.040.000.000.000.000
6.705.125.760.945.040.955.511.380.665
Is there a way to let double
calculate the result properly? BigIntegers work fine, but are much slower than the floating point types. I'm using double instead of long because I'm working with extremely large numbers.
Upvotes: 1
Views: 174
Reputation: 66
It seems the decimal type is a little bit faster than the BigInteger type.
Stopwatch stopwatch = new Stopwatch();
stopwatch.Restart();
double x = 87974894654657d;
double y = 76216354532345d;
double a = x * y;
stopwatch.Stop();
Console.WriteLine(a.ToString("n0") + " (" + stopwatch.Elapsed.TotalMilliseconds.ToString("0.000") + "ms)");
stopwatch.Restart();
BigInteger x1 = new BigInteger(87974894654657);
BigInteger y1 = new BigInteger(76216354532345);
BigInteger a1 = x1 * y1;
stopwatch.Stop();
Console.WriteLine(a1.ToString("n0") + " (" + stopwatch.Elapsed.TotalMilliseconds.ToString("0.000") + "ms)");
stopwatch.Restart();
decimal x2 = 87974894654657M;
decimal y2 = 76216354532345M;
decimal a2 = x2 * y2;
stopwatch.Stop();
Console.WriteLine(a2.ToString("n0") + " (" + stopwatch.Elapsed.TotalMilliseconds.ToString("0.000") + "ms)");
And here the output:
6.705.125.760.945.040.000.000.000.000 (0,002ms)
6.705.125.760.945.040.955.511.380.665 (0,044ms)
6.705.125.760.945.040.955.511.380.665 (0,030ms)
UPDATE:
With an iteration of 10 million the performance between the data types is even better seen:
double: 6.705.125.760.945.040.000.000.000.000 (24,558ms)
BigInteger: 6.705.125.760.945.040.955.511.380.665 (1623,420ms)
decimal: 6.705.125.760.945.040.955.511.380.665 (478,333ms)
Upvotes: 0
Reputation: 3326
Just executed
Console.WriteLine(DateTime.Now.Second+" "+DateTime.Now.Millisecond+"");
BigInteger x1 = new BigInteger(87974894654657);
BigInteger y1 = new BigInteger(76216354532345);
BigInteger a1 = x1 * y1;
Console.WriteLine(a1.ToString("n0"));
Console.WriteLine(DateTime.Now.Second+" "+DateTime.Now.Millisecond+"");
Console.WriteLine(DateTime.Now.Second+" "+DateTime.Now.Millisecond+"");
double x = 87974894654657d;
double y = 76216354532345d;
double a = x * y;
Console.WriteLine(a.ToString("n0"));
Console.WriteLine(DateTime.Now.Second+" "+DateTime.Now.Millisecond+"");
and got this result:
4 216
6,705,125,760,945,040,955,511,380,665
4 216
4 216
6,705,125,760,945,040,000,000,000,000
4 216
There wasn't a delay of even 1 millisecond.
Upvotes: 0
Reputation: 1335
Try this code:
double d = 6705125760945040955511380665d;
Console.WriteLine(d.ToString("n0"));
The output will be 6.705.125.760.945.040.000.000.000.000
. A double can represent very large values, but it cannot do it precisely. That's because it uses an exponent, a bit like adding 10^n. If you used decimals instead of binary numbers and used 4 digits you could store the number 5000000 like this: 05|06
=> 5*10^6
. The largest number you can store this way is 99|99
=> 99 * 10 ^ 99
, which is a huge number. But you cannot accurately store the number 123456, you can only approximate it: 12|04
=> 120000
.
If you want precision, don't use floating point numbers like float
or double
, use decimal
or BigInteger
instead.
Upvotes: 1
Reputation: 10208
For the output you are looking for (with "extremely large numbers") you will be constrained to use either BigInteger or decimal types.
double x = 87974894654657d;
double y = 76216354532345d;
double a = x * y;
a.Dump();
decimal xd = 87974894654657m;
decimal yd = 76216354532345m;
decimal b = xd * yd;
b.Dump();
Output:
6.70512576094504E+27
6705125760945040955511380665
Upvotes: 1