부동 데이터 형식과 10 진수 데이터 형식의 차이점 float 및

MySQL에서 float 및 decimal 데이터 형식을 사용할 때 어떤 차이점이 있습니까?

언제 사용해야합니까?



답변

이것이 내가 의심했을 때 찾은 것입니다.

mysql> create table numbers (a decimal(10,2), b float);
mysql> insert into numbers values (100, 100);
mysql> select @a := (a/3), @b := (b/3), @a * 3, @b * 3 from numbers \G
*************************** 1. row ***************************
  @a := (a/3): 33.333333333
  @b := (b/3): 33.333333333333
@a + @a + @a: 99.999999999000000000000000000000
@b + @b + @b: 100

십진수는이 경우에해야 할 일을 정확하게 수행했으며 나머지는 잘랐으므로 1/3 부분을 잃었습니다.

따라서 합계의 경우 소수점이 더 좋지만 나누기의 경우 부동 소수점이 더 좋습니다. DECIMAL을 사용해도 “실패한 산술”은 제공되지 않습니다.

도움이 되었기를 바랍니다.


답변

대부분의 환경에서 “부동”은 이진 부동 소수점 유형입니다. 기본 2 값을 특정 지점까지 정확하게 저장할 수 있지만 많은 10 기본 (10 진수) 값을 정확하게 저장할 수는 없습니다. 실수는 과학적 계산에 가장 적합합니다. 그들은 것 없는 대부분의 비즈니스 중심의 수학에 대한 적절한, 그리고 수레의 부적절한 사용은 물린 것입니다. 많은 10 진수 값은 밑이 2로 정확하게 표현 될 수 없습니다. 0.1예를 들어, 할 수 없으므로와 같은 이상한 결과가 나타납니다 1.0 - 0.1 = 0.8999999.

소수는 10 진수를 저장합니다. 10 진수는 대부분의 비즈니스 수학에 적합한 유형입니다 (그러나 기본 제공 “돈”유형은 재무 계산에 더 적합합니다). 여기서 값의 범위는 정수 유형이 제공하는 범위를 초과하고 분수 값이 필요합니다. 이름에서 알 수 있듯이 10 진법은 10 진법으로 설계되었습니다. 10 진법 값을 특정 지점까지 정확하게 저장할 수 있습니다.


답변

MySQL은 최근에 DECIMAL 유형 을 저장하는 방식을 변경했습니다 . 과거에는 숫자 대 2의 보수 정수 또는 그 파생어에 대한 ASCII (또는 nybble) 표현을 포함하는 각 숫자에 대한 문자 (또는 nybbles)를 저장했습니다.

DECIMAL의 현재 저장 형식은 일련의 1,2,3 또는 4 바이트 정수이며, 비트는 연결되어 사용자가 정의한 암시 적 소수점으로 2의 보수 수를 생성하고 선언 할 때 DB 스키마에 저장됩니다. 열을 선택하고 DECIMAL 크기와 소수점 위치를 지정하십시오.

예를 들어, 32 비트 정수를 사용하는 경우 0-4,294,967,295의 숫자를 저장할 수 있습니다. 그것은 단지 999,999,999를 확실히 커버 할 것이므로 2 비트를 버리고 (1 << 30-1) 사용하면 아무것도 포기하지 않을 것입니다. 4 바이트만으로 9 자리 숫자를 모두 처리하는 것은 4 개의 ASCII 문자 또는 8 개의 니블 숫자를 사용하여 32 비트로 4 자리를 처리하는 것보다 효율적입니다. (nybble은 4 비트이므로 0 ~ 9에 필요한 것보다 많은 0 ~ 15 값을 허용하지만 0 ~ 7의 값만 포함하므로 3 비트로 이동하여 낭비를 제거 할 수 없음)

MySQL 온라인 문서에서 사용 된 예는 DECIMAL (18,9)을 예로 사용합니다. 암시 적 소수점 뒤에 9 자리 앞뒤 9 자리이며 위에 설명 된대로 다음 저장 공간이 필요합니다.

18 개의 8 비트 문자 : 144 비트

18 비트 4 비트 니블 : 72 비트

2 개의 32 비트 정수 : 64 비트

현재 DECIMAL은 허용 된 M의 최대 값이 65이고 D의 최대 값이 30 인 DECIMAL (M, D)로 최대 65 자리를 지원합니다.

한 번에 9 자리의 청크가 필요하지 않도록 32 비트보다 작은 정수는 1, 2 및 3 바이트 정수를 사용하여 숫자를 추가하는 데 사용됩니다. 어떤 이유로 논리를 무시하고 부호없는 정수 대신 부호있는 부호가 사용되어 1 비트가 발생하여 다음과 같은 저장 기능이 제공됩니다. 1,2 및 4 바이트 정수의 경우 손실 된 비트는 중요하지 않지만 3 바이트 정수의 경우 단일 비트의 손실로 인해 전체 숫자가 손실되므로 재앙입니다.

7 비트 정수로 : 0-99

15 비트 정수로 : 0-9,999

23 비트 정수로 : 0-999,999 (24 비트 정수로 0-9,999,999)

1,2,3 및 4 바이트 정수는 함께 연결되어 “비트 풀”을 형성합니다. DECIMAL은 숫자를 2의 보수 정수로 정확하게 나타 내기 위해 사용합니다. 소수점은 저장되지 않으며 암시됩니다.

즉, “숫자”를 CPU가 숫자로 인식하는 것으로 변환하기 위해 DB 엔진에서 ASCII에서 int 로의 변환이 필요하지 않습니다. 반올림이나 변환 오류가 없으며 CPU가 조작 할 수있는 실수입니다.

이러한 종류의 숫자에 대한 하드웨어 지원이 없기 때문에이 임의의 큰 정수에 대한 계산은 소프트웨어에서 수행해야하지만,이 라이브러리는 매우 오래되고 고도로 최적화되어 있으며 50 년 전에 IBM 370 Fortran 임의 정밀도 부동 소수점 데이터를 지원하도록 작성되었습니다 . 그것들은 여전히 ​​CPU 정수 하드웨어로 수행되는 고정 크기 정수 대수 또는 FPU에서 수행되는 부동 소수점 계산보다 훨씬 느립니다.

스토리지 효율성의 관점에서, 부동 소수점은 각 부동 소수점에 첨부되므로 소수점이있는 위치를 암시 적으로 지정하므로 대량으로 중복되므로 DB 작업에 비효율적입니다. DB에서 소수점이 어디로 올라갈 지 이미 알고 있으며 DECIMAL 열에 대한 값을 가진 테이블의 모든 행은 소수점을 배치하고 저장하는 위치의 1 & 유일한 사양 만보고하면됩니다. 스키마에서 M 및 D 값의 의미로 DECIMAL (M, D)에 대한 인수로 사용됩니다.

다양한 형식의 응용 프로그램에 어떤 형식을 사용해야하는지 여기에 나와있는 많은 설명이 정확하므로 요점을 설명하지 않겠습니다. 링크 된 MySQL 온라인 문서를 유지 관리하는 사람은 위의 내용을 이해하지 못하고 그것을 포기하려는 사람들이 점점 좌절감을 느끼기 때문에이 글을 쓰는 데 시간이 걸렸습니다. 그들이 쓰고있는 내용을 얼마나 잘 이해하지 못했는지에 대한 좋은 표시는 주제에 대한 매우 혼란스럽고 거의 이해할 수없는 표현입니다.

마지막으로, 고정밀 부동 소수점 계산이 필요한 경우 지난 20 년 동안 부동 소수점 코드가 엄청나게 발전했으며 96 비트 및 쿼드 러플 정밀 부동 소수점에 대한 하드웨어 지원이 시작되었습니다 . 그러나 저장된 값의 조작이 중요한 경우 좋은 임의 정밀도 라이브러리가 있습니다.


답변

MySQL에만 국한된 것이 아니라 float 형식과 10 진수 형식의 차이는 분수 값을 나타내는 방식입니다. 부동 소수점 유형은 이진수로 분수를 나타내며으로 만 값을 나타낼 수 있습니다 {m*2^n | m, n Integers}. 1/5와 같은 값은 정확하게 반올림 할 수 없습니다 (반올림 오류 없음). 십진수는 비슷하게 제한되지만 같은 숫자를 나타냅니다 {m*10^n | m, n Integers}. 십진법은 여전히 ​​1/3과 같은 숫자를 나타낼 수는 없지만 종종 금융과 같은 많은 공통 분야에서 특정 소수 부분은 항상 충실도 손실없이 표현 될 수있을 것으로 기대합니다. 10 진수는 $0.20(1/5의 1/5) 와 같은 값을 나타낼 수 있으므로 이러한 상황에서 선호됩니다.


답변

소수는 특정 소수 자릿수를 원하는 돈과 같은 고정 수량을위한 것입니다. 부동 소수점은 부동 소수점 정밀도 숫자를 저장하기위한 것입니다.


답변

나는 이것이 유용하다는 것을 알았다.

일반적으로 부동 소수점 값은 과학 계산에는 유용하지만 재무 / 금전 값에는 사용해서는 안됩니다. 비즈니스 중심 수학의 경우 항상 10 진수를 사용하십시오.

출처 : http://code.rohitink.com/2013/06/12/mysql-integer-float-decimal-data-types-differences/


답변

mysql> CREATE TABLE num(id int ,fl float,dc dec(5,2));
Query OK, 0 rows affected (0.00 sec)


mysql> INSERT INTO num VALUES(1,13.75,13.75);
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO num VALUES(2,13.15,13.15);
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM num WHERE fl = 13.15;
Empty set (0.00 sec)

mysql> SELECT * FROM num WHERE dc = 13.15;
+------+-------+-------+
| id   | fl    | dc    |
+------+-------+-------+
|    2 | 13.15 | 13.15 |
+------+-------+-------+
1 row in set (0.00 sec)

mysql> SELECT SUM(fl) ,SUM(dc)  FROM num;
+--------------------+---------+
| SUM(fl)            | SUM(dc) |
+--------------------+---------+
| 26.899999618530273 |   26.90 |
+--------------------+---------+
1 row in set (0.00 sec)


mysql> SELECT * FROM num WHERE ABS(fl -  13.15)<0.01;
+------+-------+-------+
| id   | fl    | dc    |
+------+-------+-------+
|    2 | 13.15 | 13.15 |
+------+-------+-------+
1 row in set (0.00 sec)