双精度整数计算
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
。
如果您想要精度,请不要使用 float
或 double
等浮点数,请改用 decimal
或 BigInteger
。
刚刚执行
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)
考虑以下:
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
。
如果您想要精度,请不要使用 float
或 double
等浮点数,请改用 decimal
或 BigInteger
。
刚刚执行
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)