부동 데이터 형식과 10 진수 데이터 형식의 차이점
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 자리 숫자를 모두 처리하는 것이 ASCII 문자 4 개 또는 8 개의 니블 숫자를 사용하여 32 비트로 4 자리를 처리하는 것보다 효율적입니다. (nybble은 4 비트이므로 0-15에 필요한 것보다 많은 값을 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 온라인 문서를 유지 관리하는 사람은 위의 내용을 이해하지 못하고 그것을 포기하려고하는 좌절감이 점점 더 커지면서 여기에 글을 쓰는 데 시간이 걸렸습니다. 그들이 쓰고있는 내용을 얼마나 잘 이해하지 못했는지에 대한 좋은 표시는 주제에 대한 매우 혼란스럽고 거의 해독 할 수없는 표현입니다.
As a final thought, if you have need of high-precision floating point computation, there've been tremendous advances in floating point code in the last 20 years, and hardware support for 96-bit and Quadruple Precision float are right around the corner, but there are good arbitrary precision libraries out there if manipulation of the stored value is important.
Not just specific to MySQL, the difference between float and decimal types is the way that they represent fractional values. Floating point types represent fractions in binary, which can only represent values as {m*2^n | m, n Integers}
. values such as 1/5 cannot be precisely represented (without round off error). Decimal numbers are similarly limited, but represent numbers like {m*10^n | m, n Integers}
. Decimals still cannot represent numbers like 1/3, but it is often the case in many common fields, like finance, that the expectation is that certain decimal fractions can always be expressed without loss of fidelity. Since a decimal number can represent a value like $0.20
(one fifth of a dollar), it is preferred in those situations.
decimal is for fixed quantities like money where you want a specific number of decimal places. Floats are for storing ... floating point precision numbers.
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)
I found this useful:
Generally, Float values are good for scientific Calculations, but should not be used for Financial/Monetary Values. For Business Oriented Math, always use Decimal.
Source: http://code.rohitink.com/2013/06/12/mysql-integer-float-decimal-data-types-differences/
If you are after performance and not precision, you should note that calculations with floats are much faster than decimals
Floating-Point Types (Approximate Value) - FLOAT, DOUBLE
The FLOAT and DOUBLE types represent approximate numeric data values. MySQL uses four bytes for single-precision values and eight bytes for double-precision values.
For FLOAT, the SQL standard permits an optional specification of the precision (but not the range of the exponent) in bits following the keyword FLOAT in parentheses. MySQL also supports this optional precision specification, but the precision value is used only to determine storage size. A precision from 0 to 23 results in a 4-byte single-precision FLOAT column. A precision from 24 to 53 results in an 8-byte double-precision DOUBLE column.
MySQL permits a nonstandard syntax: FLOAT(M,D) or REAL(M,D) or DOUBLE PRECISION(M,D). Here, “(M,D)” means than values can be stored with up to M digits in total, of which D digits may be after the decimal point. For example, a column defined as FLOAT(7,4) will look like -999.9999 when displayed. MySQL performs rounding when storing values, so if you insert 999.00009 into a FLOAT(7,4) column, the approximate result is 999.0001.
Because floating-point values are approximate and not stored as exact values, attempts to treat them as exact in comparisons may lead to problems. They are also subject to platform or implementation dependencies.
For maximum portability, code requiring storage of approximate numeric data values should use FLOAT or DOUBLE PRECISION with no specification of precision or number of digits.
https://dev.mysql.com/doc/refman/5.5/en/floating-point-types.html
Problems with Floating-Point Values
Floating-point numbers sometimes cause confusion because they are approximate and not stored as exact values. A floating-point value as written in an SQL statement may not be the same as the value represented internally. Attempts to treat floating-point values as exact in comparisons may lead to problems. They are also subject to platform or implementation dependencies. The FLOAT and DOUBLE data types are subject to these issues. For DECIMAL columns, MySQL performs operations with a precision of 65 decimal digits, which should solve most common inaccuracy problems.
The following example uses DOUBLE to demonstrate how calculations that are done using floating-point operations are subject to floating-point error.
mysql> CREATE TABLE t1 (i INT, d1 DOUBLE, d2 DOUBLE);
mysql> INSERT INTO t1 VALUES (1, 101.40, 21.40), (1, -80.00, 0.00),
-> (2, 0.00, 0.00), (2, -13.20, 0.00), (2, 59.60, 46.40),
-> (2, 30.40, 30.40), (3, 37.00, 7.40), (3, -29.60, 0.00),
-> (4, 60.00, 15.40), (4, -10.60, 0.00), (4, -34.00, 0.00),
-> (5, 33.00, 0.00), (5, -25.80, 0.00), (5, 0.00, 7.20),
-> (6, 0.00, 0.00), (6, -51.40, 0.00);
mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b
-> FROM t1 GROUP BY i HAVING a <> b;
+------+-------+------+
| i | a | b |
+------+-------+------+
| 1 | 21.4 | 21.4 |
| 2 | 76.8 | 76.8 |
| 3 | 7.4 | 7.4 |
| 4 | 15.4 | 15.4 |
| 5 | 7.2 | 7.2 |
| 6 | -51.4 | 0 |
+------+-------+------+
The result is correct. Although the first five records look like they should not satisfy the comparison (the values of a and b do not appear to be different), they may do so because the difference between the numbers shows up around the tenth decimal or so, depending on factors such as computer architecture or the compiler version or optimization level. For example, different CPUs may evaluate floating-point numbers differently.
If columns d1 and d2 had been defined as DECIMAL rather than DOUBLE, the result of the SELECT query would have contained only one row—the last one shown above.
The correct way to do floating-point number comparison is to first decide on an acceptable tolerance for differences between the numbers and then do the comparison against the tolerance value. For example, if we agree that floating-point numbers should be regarded the same if they are same within a precision of one in ten thousand (0.0001), the comparison should be written to find differences larger than the tolerance value:
mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b FROM t1
-> GROUP BY i HAVING ABS(a - b) > 0.0001;
+------+-------+------+
| i | a | b |
+------+-------+------+
| 6 | -51.4 | 0 |
+------+-------+------+
1 row in set (0.00 sec)
Conversely, to get rows where the numbers are the same, the test should find differences within the tolerance value:
mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b FROM t1
-> GROUP BY i HAVING ABS(a - b) <= 0.0001;
+------+------+------+
| i | a | b |
+------+------+------+
| 1 | 21.4 | 21.4 |
| 2 | 76.8 | 76.8 |
| 3 | 7.4 | 7.4 |
| 4 | 15.4 | 15.4 |
| 5 | 7.2 | 7.2 |
+------+------+------+
5 rows in set (0.03 sec)
Floating-point values are subject to platform or implementation dependencies. Suppose that you execute the following statements:
CREATE TABLE t1(c1 FLOAT(53,0), c2 FLOAT(53,0));
INSERT INTO t1 VALUES('1e+52','-1e+52');
SELECT * FROM t1;
On some platforms, the SELECT statement returns inf and -inf. On others, it returns 0 and -0.
An implication of the preceding issues is that if you attempt to create a replication slave by dumping table contents with mysqldump on the master and reloading the dump file into the slave, tables containing floating-point columns might differ between the two hosts.
https://dev.mysql.com/doc/refman/5.5/en/problems-with-float.html
Hard & Fast Rule
If all you need to do is add, subtract or multiply the numbers you are storing, DECIMAL is best.
If you need to divide or do any other form of arithmetic or algebra on the data you're almost certainly going to be happier with float. Floating point libraries, and on Intel processors, the floating point processor itself, have TONs of operations to correct, fix-up, detect and handle the blizzard of exceptions that occur when doing typical math functions - especially transcendental functions.
As for accuracy, I once wrote a budget system that computed the % contribution of each of 3,000+ accounts, for 3,600 budget units, by month to that unit's consolidation node, then based on that matrix of percentages (3,000 + x 12 x 3,600) I multiplied the amounts budgeted by the highest organizational nodes down to the next 3 levels of the organizational nodes, and then computed all (3,000 + 12) values for all 3,200 detail units from that. Millions and millions and millions of double precision floating point calculations, any one of which would throw off the roll-up of all of those projections in a bottoms-up consolidation back to the highest level in the organization.
The total floating point error after all of those calculations was ZERO. That was in 1986, and floating point libraries today are much, much better than they were back then. Intel does all of it's intermediate calculations of doubles in 80 bit precision, which all but eliminates rounding error. When someone tells you "it's floating point error" it's almost certainty NOT true.
float
(and double
) represents binary fractions
decimal
represents decimal fractions
declare @float as float(10)
declare @Decimal as decimal(10)
declare @Inetger as int
set @float =10.7
set @Decimal =10.7
set @Inetger=@Decimal
print @Inetger
in float when set value to integer print 10 but in decimal 11
참고URL : https://stackoverflow.com/questions/5150274/difference-between-float-and-decimal-data-type
'IT story' 카테고리의 다른 글
JavaScript로 객체를 만드는 데 가장 좋은 방법은 무엇입니까? (0) | 2020.05.24 |
---|---|
가장 일반적인 SVN은 패턴을 무시합니까? (0) | 2020.05.24 |
메모장 ++ 텍스트 편집기에서 배경색을 변경하는 방법은 무엇입니까? (0) | 2020.05.24 |
항상 android : configChanges =“keyboardHidden | orientation”을 사용하지 않는 이유는 무엇입니까? (0) | 2020.05.24 |
Linux에서 전체 CPU 사용량 (예 : 57 %)을 얻는 방법 (0) | 2020.05.24 |