database.sarang.net
UserID
Passwd
Database
DBMS
MySQL
PostgreSQL
ㆍFirebird
Oracle
Informix
Sybase
MS-SQL
DB2
Cache
CUBRID
LDAP
ALTIBASE
Tibero
DB 문서들
스터디
Community
공지사항
자유게시판
구인|구직
DSN 갤러리
도움주신분들
Admin
운영게시판
최근게시물
Firebird Columns 89 게시물 읽기
No. 89
[버그] FLOAT 데이터타입의 오묘한 버그
작성자
박정훈(duf2wjs)
작성일
2005-09-27 19:13
조회수
15,907

오랜만에 글 올립니다. 사용하시고 계신분들은 이미 알고 계시겠지만 행여나 싶어서 글올립니다.

몇가지 버그를 발견하긴 했지만 하나하나 올리도록 하겠습니당..

---------------------------------------------------------------------

먼저 FLOAT 의 버그 첫번째

 

SQL>CREATE TABLE member ( pay FLOAT );

SQL>INSERT INTO member VALUES ('20.22');

SQL>INSERT INTO member VALUES ('30.33');

SQL>SELECT SUM(pay), AVG(pay) FROM member;

 

결과는?

SUM AVG
======================= =======================

50.54999923706055 25.27499961853027

 

이런 좀 어이없는 결과를 내뱉습니다. ^ㅡ^;;

 

---------------------------------------------------------------------

FLOAT의 두번째버그

SQL> insert into member (pay) values ('12.3456789');

SQL>select * from member;

 

PAY
==============

12.345679

 

보시는 바와 같이 소수부의 마지막 두번째 자리인 8은 어디론가 사라져 버렸습니다.

 

다음엔 DECIMAL 과 NUMERIC의 버그를 써보도록 하겠습니당.. 잇힝~~

 

 

 

 

 

 

이 글에 대한 댓글이 총 3건 있습니다.

글쎄요...어떻게 보면 버그라고 할수도 있고...어떻게 보면 아닌것 같고...정말 오묘` 한 버그라구 할수 있겟습니다. ^^

 

아마 정밀도의 차이가 아닐까 싶습니다. (왜 불새에서는 float는 decimal 처럼 소숫점이하 자릿수를 정하지 못하게 한것인지 궁금하기 따름입니다.)

 

float 로 정하면 소숫점자릿수가 6자리로 되어지느듯 합니다. (그렇다고 해도 20.22 를 넣으면 20.220000 이 되어야 하는데..20.219999 이렇게 저장이 된다는건...난감하기 그지 없긴 합니다. )

 

sum(pay) 50.54999923... 는 반올림되면 50.55 가 맞지요...-,.ㅡ;;; 난감하긴 합니다만....

 

두번째 항목도 역시....12.3456789 에서 소수부가 7자리여서 마지막 9가 짤리면서 반올림된것 같습니다. 12.7654321 를 입력하면 12.765432 가 저장이 됩니다.

 

흠...거 참~...오묘하네요...

team b(teamb)님이 2005-10-05 14:27에 작성한 댓글입니다.

과연 파이어버드의 문제 일까요?

실수연산에는 모두 이런 문제가 있습니다.

그리고 거의 모든 언어(현재 C, Pascal 등등) 는 이런 문제가 있을꺼에요

데브피아나 델파이포럼에 들어가시면 이 문제에 대해서 엄청 많이 올라 옵니다.

안 예로 다음과 같아요

var

  aa, cc : extended;

  bb : int64;

begin

  aa := 1000.0;

  cc := aa * 0.001;

  bb := trunc(cc);

 

사람이 알기로는 1 입니다. 결과도 1이 나와야 합니다.

그러나 0 입니다. (cc 에는 0.9999999987... 저장됨)

 

다만 파이어버드만의 문제는 아닙니다 실수의 정밀도를 기준으로 잘 사용하시면 됩니다.

참고로 Trunc함수는 잘라버리는 함수 이므로 사용시 매우 조심해야 하는 함수 이고요

 

그리고 과거에 경험했던 일 소개 할께요

DB는 Mysql 이고 언어는 델파이로 했어요

델파이에서는 Time이 Double형식입니다.

 

var

  T : Array[0..99] of Double;

  i  : integer;

begin

   for i := 0 to 99 do

   begin

      T[i] := roundto(now, 1, -6);

      sleep(1);

      ///////////

         Mysql에 저장

      ///////////

   end;

end;

이러면 실제적으로 소수점 6자리까지만 DB에 저장되어야 합니다.

그러나 Select해보면 실제와는 다르게 저장됨을 알 수 있습니다.

 

그러니 파이어버드의 버그라고 보기 어렵습니다.

 

이중철(gosrak)님이 2005-10-07 11:07에 작성한 댓글입니다.
이 댓글은 2005-10-07 11:22에 마지막으로 수정되었습니다.

네, 부동소숫점 연산은 오래전부터 논의가 많았었죠...게다가 CPU에 따라서도 차이가 많습니다. 이유는 아시리라 믿습니다.

 

지정한 크기 외에는 쓰레기값이 채워지기 때문이지요.

 

델파이에서는 single,double,extended...등 각 자료형의 크기에 따라서 지정된 자릿수가 있습니다.  헬프를 보시면 아시겟지만 Significant digits 가 바로 그거죠...

 

double 의 경우 15~16 이라고 되어 있는데, 15~16 자리까지 유효하고 그 뒤부터는 쓰레기값일수 있습니다.

 

이는 각 컴파일러나 언어에 따라서 다르고, 또한 CPU에 따라서 다른것으로 알고 있습니다.

 

(에휴 ~ 그러고 보니 예전에 round, trunc함수군들...크크 무자게 속썩었던게 생각이 나는군요...(~-,.ㅜ)~

 

흠...그런데 여기서 다른것을 논할것 까지는 없을것 같은데요? ^^ 뭐 불새가 델파이로 작성되었다면은 모를까?

 

예를 들어서 MySQL로 한번 들어볼께요...(사실 저위와 같은 문제는 MySQL에서도 벌어지더군요)

 

create table test (f1 float, f2 float(10,2));

insert into test values (20.22,30.33);

insert into test values (1/3, 1/3);

select * from test;

--> 20.22, 30.33

--> 0.333333, 0.33

 

어떤가요? f1,f2 둘다 float 형 이지만, f2 의 경우 소수부의 자릿수를 확실하게 정했습니다. 다라서 2자리 이후부터는 다 짤라버리죠. 역시 MySQL에서도 자릿수를 정하지 않으면 소수부 6자리 까지 들어갑니다. (델파이에서 single형이 7~8자리까지 유효합니다. 대충 비슷하죠?) 6자리 이후부터는 쓰레기라고 봐도 무방합니다.

 

create table test1 (f1 float);

insert into test1 values (20.22),(30.33);

select * from test1;

--> 20.22

--> 30.33

정상적으로 보이나요?

select sum(f1) , avg(f1) from test1;

어떤가요?

 

위의 불새와 마찬가지의 현상을 보입니다. 자릿수를 정하고 한번 해보시면 차이점을 알수 있을것입니다.

 

사실 버그도 아닙니다. -,.ㅡ (마치 예전에 round 함수에 대한 버그토론처럼여...) 아쉬운것은 불새에서 float 형에 대해서 decimal, numeric 처럼 자릿수를 정하지 못하게 해놨다는게 문제일수 있겟죠.

 

어쩌면 불새에서 저러한 문제에 대해서 문서로 뭔가 남겨놓지 않았을까 하는 생각이 드는군요. (흠..찾지는 못하겟군요...ㅠㅠ)

 

그럼...

 

 

team b(teamb)님이 2005-10-07 16:14에 작성한 댓글입니다.
[Top]
No.
제목
작성자
작성일
조회
95[정보] PAGE_SIZE, LENGTH, DB파일사이즈의 관계
박정훈
2006-05-05
12012
90[버그] isql 의 input 문의 버그
박정훈
2006-02-13
10956
89[버그] FLOAT 데이터타입의 오묘한 버그 [3]
박정훈
2005-09-27
15907
79오라클의 substr와 UDF의 substr는 같지 않습니다.
이중철
2006-01-20
12783
36Firebird vs IBM vs Oracle
이창민
2005-08-02
11899
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2023 DSN, All rights reserved.
작업시간: 0.049초, 이곳 서비스는
	PostgreSQL v16.1로 자료를 관리합니다