Microsoft ACE driver을 사용하여 Excel 스프레드 시트를 연 후 일부 계산 결과가 변경되는 것으로 보이는 문제가 있습니다.Microsoft ACE 드라이버가 나머지 프로그램에서 부동 소수점 정밀도를 변경합니다.
코드는 문제를 재현합니다.
DoCalculation
에 대한 처음 두 건은 동일한 결과를 산출합니다. 그런 다음 ACS 드라이버를 사용하여 Excel 2003 스프레드 시트를 열고 닫는 OpenSpreadSheet
함수를 호출합니다. DoCalculation
에 대한 마지막 호출에 OpenSpreadSheet
이 아무런 영향을 미치지 않을 것으로 예상되지만 결과는 실제로 변경됩니다. 프로그램에서 생성하는 출력은 다음과 같습니다.
1,59142713593566
1,59142713593566
1,59142713593495
마지막 3 자리수의 차이점에 유의하십시오. 이것은 큰 차이점처럼 보이지는 않지만 생산 코드에서 계산은 복잡하며 결과 차이는 상당히 큽니다.
ACE 드라이버 대신 JET 드라이버를 사용하면 아무런 차이가 없습니다. 형식을 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
}
}
}
철저한 답변 해 주셔서 감사합니다. 한 가지 결과가 다른 것보다 정확하지 않다는 것을 알고 있지만 ACE 드라이버가 동일한 프로세스 내에서 계산을 변경하는 이러한 부작용을 가지고 있다는 것이 문제입니다. 나는 당신의 방법을 시도하고 그들은 둘 다 작동합니다. 예외 메서드는 디버그 빌드에서만 작동합니다. 시간 내 주셔서 감사합니다. –
흠, 아니요,이 재설정은 릴리스 빌드에서도 수행됩니다. 이 코드는 CLR 내부에 있으며 프로그램을 작성한 방식에 영향을받지 않습니다. 마지막 단락을 명심하십시오. 디버거가 연결되어 있는지 여부에 따라 릴리스 빌드에서 다른 결과가 나옵니다. –
오, 내 실수. exeption 메서드는 RELEASE 빌드에서만 작동합니다. 디버그 빌드가 아닙니다. –