我遇到了一个问题,在使用Microsoft ACE 驱动程序打开 Excel 电子表格后,某些计算的结果似乎发生了变化。
下面的代码重现了该问题。
前两个调用DoCalculation
产生相同的结果。然后我调用OpenSpreadSheet
使用 ACE 驱动程序打开和关闭 Excel 2003 电子表格的函数。您不会期望OpenSpreadSheet
对最后一次调用有任何影响,DoCalculation
但事实证明结果实际上发生了变化。这是程序生成的输出:
1,59142713593566
1,59142713593566
1,59142713593495
注意最后 3 位小数的差异。这看起来差别不大,但在我们的生产代码中,计算很复杂,由此产生的差异非常大。
如果我使用 JET 驱动程序而不是 ACE 驱动程序,这没有什么区别。如果我将类型从 double 更改为 decimal,错误就会消失。但这不是我们的生产代码中的选项。
我在 Windows 7 64 位上运行,程序集是为 .NET 4.5 x86 编译的。使用 64 位 ACE 驱动程序不是一个选项,因为我们正在运行 32 位 Office。
有谁知道为什么会发生这种情况以及我该如何解决?
以下代码重现了我的问题:
static void Main(string[] args)
{
DoCalculation();
DoCalculation();
OpenSpreadSheet();
DoCalculation();
}
static void DoCalculation()
{
// Multiply two randomly chosen number 10.000 times.
var d1 = 1.0003123132;
var d3 = 0.999734234;
double res = 1;
for (int i = 0; i < 10000; i++)
{
res *= d1 * d3;
}
Console.WriteLine(res);
}
public static void OpenSpreadSheet()
{
var cn = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;data source=c:\temp\workbook1.xls;Extended Properties=Excel 8.0");
var cmd = new OleDbCommand("SELECT [Column1] FROM [Sheet1$]", cn);
cn.Open();
using (cn)
{
using (OleDbDataReader reader = cmd.ExecuteReader())
{
// Do nothing
}
}
}