双精度整数计算

Precise whole number calculation with double

考虑以下:

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"));

输出:

6.705.125.760.945.040.000.000.000.000
6.705.125.760.945.040.955.511.380.665

有没有办法让double正确计算出结果? BigIntegers 工作正常,但比浮点类型慢得多。我使用 double 而不是 long,因为我处理的是非常大的数字。

对于您要查找的输出("extremely large numbers"),您将只能使用 BigInteger 或 decimal 类型。

double x = 87974894654657d;
double y = 76216354532345d;
double a = x * y;
a.Dump();


decimal xd = 87974894654657m;
decimal yd = 76216354532345m;
decimal b = xd * yd;
b.Dump();

输出:

6.70512576094504E+27
6705125760945040955511380665

试试这个代码:

        double d = 6705125760945040955511380665d;
        Console.WriteLine(d.ToString("n0"));

输出将是 6.705.125.760.945.040.000.000.000.000。 double 可以表示非常大的值,但不能精确地表示。那是因为它使用了一个指数,有点像加 10^n。如果您使用小数而不是二进制数并使用 4 位数字,您可以像这样存储数字 5000000:05|06 => 5*10^6。您可以通过这种方式存储的最大数字是 99|99 => 99 * 10 ^ 99,这是一个巨大的数字。但是你不能准确存储123456这个数字,只能近似:12|04 => 120000

如果您想要精度,请不要使用 floatdouble 等浮点数,请改用 decimalBigInteger

刚刚执行

     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+"");

得到这个结果:

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

连 1 毫秒的延迟都没有。

decimal类型好像比BigInteger类型快一点

        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)");

这里输出:

6.705.125.760.945.040.000.000.000.000(0,002 毫秒)

6.705.125.760.945.040.955.511.380.665(0,044 毫秒)

6.705.125.760.945.040.955.511.380.665(0,030 毫秒)

更新:

随着 1000 万次迭代,数据类型之间的性能更加明显:

双:6.705.125.760.945.040.000.000.000.000(24,558 毫秒)

大整数:6.705.125.760.945.040.955.511.380.665(1623,420 毫秒)

十进制:6.705.125.760.945.040.955.511.380.665 (478,333ms)