소수 열에 돈 저장-정밀도와 스케일은?
데이터베이스에 돈 값을 저장하기 위해 10 진수 열을 사용하고 있으며 오늘 사용할 정밀도와 스케일이 궁금합니다.
고정 너비의 문자 열이 더 효율적이라고 가정하기 때문에 십진 열에 대해서도 마찬가지라고 생각했습니다. 그렇습니까?
그리고 어떤 정밀도와 스케일을 사용해야합니까? 나는 24/8의 정밀도를 생각하고있었습니다. 그 잔인 함은 충분하지 않습니까?
이것이 내가하기로 결정한 것입니다.
- 거래 테이블 자체에 전환율 (해당되는 경우)을 플로트로 저장
- 계정 테이블에 통화 저장
- 거래 금액은
DECIMAL(19,4)
- 변환율을 사용한 모든 계산은 내 응용 프로그램에서 처리되므로 반올림 문제를 계속 제어합니다.
전환율에 대한 플로트는 대부분 참조 용이므로 문제가되지 않는다고 생각합니다. 어쨌든 10 진수로 캐스팅 할 것입니다.
소중한 의견을 보내 주셔서 감사합니다.
한 가지 크기의 제품을 찾고 있다면 DECIMAL(19, 4)
인기있는 선택 이라고 제안 합니다 (Google이 신속하게 처리합니다). 나는 이것이 구 VBA / 액세스 / 제트 통화 데이터 타입에서 유래 한 것으로 생각한다. Decimal
VB6 / VBA6 / Jet 4.0에서는 '버전 1.0'스타일 (즉, 완전히 구현되지 않음) 만있었습니다.
고정 소수점 10 진수 값 을 저장 하기위한 경험의 규칙은 실제로 반올림을 허용하는 데 필요한 것보다 적어도 하나 이상의 소수점을 저장하는 것입니다. Currency
프런트 엔드 의 이전 유형을 DECIMAL(19, 4)
백 엔드의 유형으로 매핑하는 이유 중 하나 Currency
는 뱅커의 반올림을 자르고 반올림으로 반올림 했기 때문 DECIMAL(p, s)
입니다.
저장소에 여분의 소수 자릿수를 DECIMAL
사용하면 공급 업체의 기본값을 사용하지 않고 사용자 지정 반올림 알고리즘을 구현할 수 있습니다 (그리고 은행가의 반올림은 놀랍습니다. .
그렇습니다 DECIMAL(24, 8)
. 대부분의 통화는 소수점 이하 네 자리로 인용됩니다. 나는 8 (또는 그 이상)의 소수 자릿수 가 필요한 상황을 알고 있지만 이것은 '정상적인'금액 (소수 자릿수 네 자리)이 비례하여 소수점 이하 자릿수가 그에 따라 감소해야 함을 암시합니다 (또한 고려하십시오) 이러한 상황에서 부동 소수점 유형). 그리고 오늘날 아무도 십진수 정밀도 24를 요구할만큼 많은 돈이 없습니다 :)
그러나 모든 규모에 맞는 접근법이 아닌 일부 연구는 순서대로 진행될 수 있습니다. GAAP, EU 등 적용 가능한 회계 규칙에 대해 설계자 또는 도메인 전문가에게 문의하십시오. 소수의 다섯 자리로 반올림하기위한 명시적인 규칙을 사용하여 일부 EU 내 국가 간 전송을 모호하게 기억하므로 DECIMAL(p, 6)
저장에 사용 합니다. 회계사는 일반적으로 소수점 이하 네 자리를 선호하는 것 같습니다.
PS MONEY
반올림시 정확성과 심각한 문제가 있으므로 SQL Server의 데이터 유형을 피하십시오 . 이식성 등과 같은 다른 고려 사항도 있습니다. Aaron Bertrand의 블로그를 참조하십시오 .
하드웨어 디자이너가 그것을 인용했기 때문에 마이크로 소프트와 언어 디자이너는 은행가의 반올림을 선택했습니다. 예를 들어 IEEE (Institute of Electrical and Electronics Engineers) 표준에 명시되어 있습니다. 그리고 수학자들이 선호하기 때문에 하드웨어 설계자들이 그것을 선택했습니다. Wikipedia를 참조하십시오 . 역설 : 1906 년 확률과 오류 이론은 이것을 '컴퓨터의 규칙'(계산을 수행하는 인간을 의미하는 "컴퓨터")이라고 불렀습니다.
우리는 최근 여러 통화로 값을 처리하고 그 사이에서 변환 해야하는 시스템을 구현했으며 어려운 몇 가지 사항을 알아 냈습니다.
돈에 부동 소수점 숫자를 사용하지 마십시오
부동 소수점 산술은 무언가를 망칠 때까지 눈에 띄지 않을 수있는 부정확성을 초래합니다. 모든 값은 정수 또는 고정 소수점 형식으로 저장해야하며, 고정 소수점 형식을 사용하기로 선택한 경우 해당 형식이 후드에서 수행하는 작업을 정확히 이해해야합니다 (예 : 내부적으로 정수 또는 부동 소수점을 사용합니까) 유형).
계산 또는 변환이 필요한 경우 :
- 값을 부동 소수점으로 변환
- 새로운 가치를 계산
- 숫자를 반올림하고 다시 정수로 변환
3 단계에서 부동 소수점 숫자를 다시 정수로 변환 할 때는 캐스트하지 말고 수학 함수를 사용하여 먼저 반올림하십시오. round
특별한 경우에는 floor
또는 일 수 있지만 이것은 보통 일 것이다 ceil
. 차이점을 알고 신중하게 선택하십시오.
값과 함께 숫자 유형을 저장하십시오.
하나의 통화 만 처리하는 경우에는 이것이 중요하지 않을 수 있지만 여러 통화를 처리하는 데 중요했습니다. USD, GBP, JPY, EUR 등과 같은 통화에 3 자 코드를 사용했습니다.
상황에 따라 다음을 저장하는 것이 도움이 될 수도 있습니다.
- 숫자가 세전 또는 후인지 여부 및 세율
- 숫자가 변환의 결과인지 여부 및 변환 된 결과
당신이 다루고있는 숫자의 정확도 한계를 아십시오
실제 가치의 경우 가장 작은 통화 단위만큼 정확해야합니다. 이는 1 센트, 1 페니, 엔, 펜 등의 값이 없다는 것을 의미합니다. 아무 이유없이 그 값보다 높은 정확도로 값을 저장하지 마십시오.
내부적으로 더 작은 값을 처리하도록 선택할 수 있으며,이 경우 다른 통화 값 유형입니다 . 코드가 어느 것을 알고 있고 혼동하지 않도록하십시오. 여기에서도 부동 소수점 값을 사용하지 마십시오.
이러한 규칙을 모두 추가하여 다음 규칙을 결정했습니다. 실행 코드에서 통화는 가장 작은 단위의 정수를 사용하여 저장됩니다.
class Currency {
String code; // eg "USD"
int value; // eg 2500
boolean converted;
}
class Price {
Currency grossValue;
Currency netValue;
Tax taxRate;
}
데이터베이스에서 값은 다음 형식으로 문자열로 저장됩니다.
USD:2500
그것은 $ 25.00의 가치를 저장합니다. 통화를 처리하는 코드가 데이터베이스 계층 자체 내에있을 필요가 없으므로 모든 값을 먼저 메모리로 변환 할 수 있기 때문에 그렇게 할 수있었습니다. 다른 상황은 의심 할 여지없이 다른 솔루션에 적합합니다.
그리고 내가 일찍 그것을 명확하게 하지 않은 경우, float을 사용하지 마십시오!
When handling money in MySQL, use DECIMAL(13,2) if you know the precision of your money values or use DOUBLE if you just want a quick good-enough approximate value. So if your application needs to handle money values up to a trillion dollars (or euros or pounds), then this should work:
DECIMAL(13, 2)
Or, if you need to comply with GAAP then use:
DECIMAL(13, 4)
4 decimal places would give you the accuracy to store the world's smallest currency sub-units. You can take it down further if you need micropayment (nanopayment?!) accuracy.
I too prefer DECIMAL
to DBMS-specific money types, you're safer keeping that kind of logic in the application IMO. Another approach along the same lines is simply to use a [long] integer, with formatting into ¤unit.subunit for human readability (¤ = currency symbol) done at the application level.
The money datatype on SQL Server has four digits after the decimal.
From SQL Server 2000 Books Online:
Monetary data represents positive or negative amounts of money. In Microsoft® SQL Server™ 2000, monetary data is stored using the money and smallmoney data types. Monetary data can be stored to an accuracy of four decimal places. Use the money data type to store values in the range from -922,337,203,685,477.5808 through +922,337,203,685,477.5807 (requires 8 bytes to store a value). Use the smallmoney data type to store values in the range from -214,748.3648 through 214,748.3647 (requires 4 bytes to store a value). If a greater number of decimal places are required, use the decimal data type instead.
Sometimes you will need to go to less than a cent and there are international currencies that use very large demoniations. For example, you might charge your customers 0.088 cents per transaction. In my Oracle database the columns are defined as NUMBER(20,4)
If you're going to be doing any sort of arithmetic operations in the DB (multiplying out billing rates and so on), you'll probably want a lot more precision than people here are suggesting, for the same reasons that you'd never want to use anything less than a double-precision floating point value in application code.
If you were using IBM Informix Dynamic Server, you would have a MONEY type which is a minor variant on the DECIMAL or NUMERIC type. It is always a fixed-point type (whereas DECIMAL can be a floating point type). You can specify a scale from 1 to 32, and a precision from 0 to 32 (defaulting to a scale of 16 and a precision of 2). So, depending on what you need to store, you might use DECIMAL(16,2) - still big enough to hold the US Federal Deficit, to the nearest cent - or you might use a smaller range, or more decimal places.
I would think that for a large part your or your client's requirements should dictate what precision and scale to use. For example, for the e-commerce website I am working on that deals with money in GBP only, I have been required to keep it to Decimal( 6, 2 ).
A late answer here, but I've used
DECIMAL(13,2)
which I'm right in thinking should allow upto 99,999,999,999.99.
'IT박스' 카테고리의 다른 글
Angularjs 코드 / 이름 지정 규칙 (0) | 2020.06.02 |
---|---|
라텍스에서 목록을 여러 열로 나누기 (0) | 2020.06.02 |
IValidatableObject를 어떻게 사용합니까? (0) | 2020.06.02 |
MongoDB 데이터베이스 파일 크기 줄이기 (0) | 2020.06.02 |
디자인 패턴 : 팩토리 vs 팩토리 메소드 vs 추상 팩토리 (0) | 2020.06.02 |