[ACCESS] Round 함수의 결과값 반환에 대한 이해.

 

 

 

몇일 전 Round함수가 잘못 작동하고 있다는 글을 포스팅하였다.

 

 

하지만  설마하니 Round같은 기초 함수를 설계하는데 버그를 낼리가 없을거라는 생각에 조금 더 조사를 해 보았더니 역시 이것은 의도된 것이었음을 알게 되었다.

그리고 그것이 보다 정확한 결과를 위해서 라는 것도..

 

 

 

이 글을 보니 단숨에 이해가 되었다.

 

 

요지는 이렇다.

 

정수 1개를 기준으로  0.1 ~ 0.9 까지 소수 9개가 반올림 대상 숫자가 된다.

0.1~0.4까지 4개의 소수는 내림 처리를 하게 되고

0.5~0.9까지 5개의 소수는 올림 처리를 하게 된다.

 

이렇게 되면 버려지는 숫자는 4개, 올려지는 숫자는 5개이므로 정수1개당  1/9만큼 불공평하게 나누어진다는 것이다.

살짝 표로 보자면..

 1.0

 2.0

 3.0

 4.0

 1.1 

 2.1

 3.1

 4.1

 1.2

 2.2

 3.2

 4.2

 1.3

 2.3

 3.3

 4.3

 1.4

 2.4

 3.4

 4.4

 1.5

 2.5

 3.5

 4.5

 1.6

 2.6

 3.6

 4.6

 1.7

 2.7

 3.7

 4.7

 1.8

 2.8

 3.8

 4.8

 1.9

 2.9

 3.9

 4.9

 

1.0~4.0까지 숫자 40개 중에서 변하지 않는 숫자는 4개이고

버려지는 숫자는 16개, 올려지는 숫자는 20개이다. 올려지는 숫자가 더 많다..

 

 

그럼 위 링크의 'Banker's Rounding'의 규칙을 적용해 본다면

 

 1.0

 2.0

 3.0

 4.0

 1.1 

 2.1

 3.1

 4.1

 1.2

 2.2

 3.2

 4.2

 1.3

 2.3

 3.3

 4.3

 1.4

 2.4

 3.4

 4.4

 1.5

 2.5

 3.5

 4.5

 1.6

 2.6

 3.6

 4.6

 1.7

 2.7

 3.7

 4.7

 1.8

 2.8

 3.8

 4.8

 1.9

 2.9

 3.9

 4.9

1.0~4.0까지 숫자 40개 중에서 변하지 않는 숫자는 똑같이 4개이고

버려지는 숫자는 18개올려지는 숫자도 18개이다.

 

 

실제로 여러 값의 반올림을 평균한다던지 하는 집계쪽에는 이 방법이  더 근사치와 가까워 질 것이 확실해 보인다.

하지만 개인의 성적을 처리할 경우에는 맞지 않는다. 97.5점을 받아도 98점이고, 98.5점을 받아도 98점이 되버리니..

 

여튼 이제껏 생각 못하고 그냥 마구잡이로 Round를 써왔는데 이번을 계기로 알게 되었으니 앞으로는 상황을 고려해 사용하도록 해야겠다.

[ACCESS] 엑세스의 Round 함수의 버그? 오작동 사례.

 

 

Access를 이용해 데이터 처리를 하던 도중 의도치 않는 결과가 나온다는 보고가 있어서 찾아보았다.

흔히 반올림 처리를 위해 사용하Round 함수가 특정 규칙을 가지고 오작동을 하고 있었다.

0.5 => 1

1.5 => 2

2.5 => 2

3.5 => 4

4.5 => 4

5.5 => 6

6.5 => 6

....

이렇게 격수로 하나씩 건너뛰면서 반올림, 내림, 반올림, 내림 처리를 하고 있는 것이었다.

 

 

증거자료..

 

 

 아래와 같이 실수(Single)타입의 값1~값6 필드를 가진 테이블을 만들어서 값들을 채워넣고..

 

 

 

아래의 쿼리를 돌려서 나온 결과..

SELECT
SUM(값1) AS 원값
,SUM(값2) AS [원값빼기05]
,SUM(값3) AS [원값빼기1]
,SUM(값4) AS [원값빼기15]
,SUM(값5) AS [원값빼기25]
,SUM(값6) AS [원값빼기35]
FROM 테이블1

UNION ALL

SELECT
ROUND(SUM(값1),0)
,ROUND(SUM(값2),0)
,ROUND(SUM(값3),0)
,ROUND(SUM(값4),0)
,ROUND(SUM(값5),0)
,ROUND(SUM(값6),0)
FROM 테이블1;

결과를 보면 17.5는 정상적으로 18로 반올림 처리가 되었으나  12.5의 반올림은 13이 되지 않고 12가 되었다.

역시 7.5는 반올림되어 8이 되었으나 2.5는 내림이 되어 2가 되어버렸다.

 

추측하기에는 실수(Single)값의 부동소숫점 연산 처리때문에 그런게 아닐까 싶지만..

별생각없이 반올림 처리하려고 Round를 자주 쓰게 되는데  이러면 곤란하다..

특히 이건 SAT 채점의 Omit처리를 하다 발견된 건데,, 점수의 계산이 틀어지면 끝장이지 않은가.

 

해서 해결방안은. Round함수를 뜯어고칠수는 없으니,,

Round(SUM(값1)+0.1 , 0) 으로  일괄적으로 0.1을 더해주었다. 정수반올림을 하는데에는 0.1 더해주는거면 충분함..

ADODB나 OLEDB로 ACCESS DB(mdb, accdb)를 사용할 때.

 

일련번호 형식의 SEQ라던지 Identity 필드값을 초기화 하는 방법.

 

참고로 MS-SQL 에서는 이렇게 처리한다.

 

DBCC CHECKIDENT('테이블명',RESEED,0)

이렇게 하면 다음번 insert시에  시드가 1부터 시작하게 되고..

 

DBCC CHECKIDENT('테이블명',RESEED,9999)

이렇게 하면 10000부터 시작된다.

 

 

 

이걸 엑세스(access 2007 에서만 해봤음)  에서 구현하려면~

 

ALTER TABLE [테이블명] ALTER COLUMN [컬럼명] COUNTER(1,1)

 

무슨.... 엑세스에 가서 데이터베이스 압축/복구를 하라느니 복잡하고 귀찮은 설명이 있는데

 

외부프로그램에서나 엑세스 내부에서나  위 쿼리를 한번 돌려주면 끝남. 단, 그전에 테이블의 모든 데이터를 삭제하고 해야함.

 

또한 PK,FK 등  관계가 걸려있는 경우에는 안 될수도 있음..

 

+ Recent posts