Драйвер Microsoft ACE изменяет точность с плавающей запятой в остальной части моей программы
У меня возникла проблема, когда кажется, что результаты некоторых вычислений меняются после использованияMicrosoft ACE драйвер открыть электронную таблицу Excel.
Код ниже воспроизводит проблему.
Первые два звонкаDoCalculation
дают одинаковые результаты. Тогда я вызываю функциюOpenSpreadSheet
который открывает и закрывает электронную таблицу Excel 2003 с помощью драйвера ACE. Вы не ожидаетеOpenSpreadSheet
иметь какое-либо влияние на последний звонокDoCalculation
но получается, что результат действительно меняется. Это вывод, который генерирует программа:
1,59142713593566
1,59142713593566
1,59142713593495
Обратите внимание на различия в последних 3 десятичных разрядах. Это не кажется большой разницей, но в нашем производственном коде вычисления сложны, и результирующие различия довольно велики.
Не имеет значения, если я использую драйвер JET вместо драйвера ACE. Если я изменю типы с двойного на десятичный, ошибка исчезнет. Но это не вариант в нашем производственном коде.
Я использую 64-разрядную версию Windows 7, и сборки скомпилированы для .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
}
}
}