다음 대신 double
(또는 float
) 을 사용하면 다음과 같은 세 가지 장점을 말할 수 있습니다 decimal
.
- 적은 메모리를 사용합니다.
- 부동 소수점 연산은 프로세서에서 기본적으로 지원하기 때문에 더 빠릅니다.
- 더 큰 숫자 범위를 나타낼 수 있습니다.
그러나 이러한 장점은 모델링 소프트웨어에서 볼 수있는 계산 집약적 인 작업에만 적용되는 것으로 보입니다. 물론 재무 계산과 같이 정밀도가 필요한 경우에는 복식을 사용해서는 안됩니다. 그래서 지금 선택할 수있는 실제적인 이유가 double
(또는 float
대신) decimal
“정상”애플리케이션은?
추가 편집 : 모든 훌륭한 답변에 감사드립니다.
또 다른 질문 : 소수의 사람들은 복식이 실수를보다 정확하게 표현할 수 있다고 지적했습니다. 선언했을 때 나는 그들이 더 정확하게 표현할 것이라고 생각합니다. 그러나 부동 소수점 연산을 수행 할 때 정확도가 저하 될 수 있다는 사실이 사실입니까?
답변
이점을 잘 요약했다고 생각합니다. 그러나 당신은 한 가지 점이 없습니다. 이 decimal
유형은 기본 10 개 숫자 (예 : 통화 / 재무 계산에 사용되는 숫자) 를 나타내는 데있어 더 정확 합니다. 일반적으로 double
유형은 적어도 큰 정밀도 (잘못되면 누군가를 수정합니다)와 임의의 실수에 대해 확실히 더 빠른 속도를 제공 할 것입니다. 간단한 결론은 : 사용할 것을 고려할 때 제공 double
하는 base 10
정확성이 필요하지 않은 한 항상 사용 하십시오 decimal
.
편집하다:
연산 후 부동 소수점 숫자의 정확도 감소에 대한 추가 질문과 관련하여 약간 더 미묘한 문제입니다. 실제로, 각 작업이 수행 된 후 정밀도 (여기서 정확도를 위해 상호 교환 가능하게 사용하는 용어를 사용함)는 꾸준히 감소합니다. 이것은 두 가지 이유 때문입니다.
- 특정 숫자 (가장 명백하게 십진법)를 부동 소수점 형태로 표현할 수 없다는 사실
- 손으로 계산하는 것처럼 반올림 오류가 발생합니다. 그러나 이러한 오류가 많은 생각을 할만큼 충분히 중요한지의 여부 (실제로 수행중인 작업 수)에 따라 크게 달라집니다.
모든 경우에 이론적으로 동일하지만 다른 계산을 사용하여 도달 한 두 개의 부동 소수점 숫자를 비교하려면 어느 정도의 허용 오차 (얼마나 많은 차이가 있지만 일반적으로 매우 작은 지)를 허용해야합니다. .
정확도 오류가 발생할 수있는 특정 사례에 대한 자세한 개요는 Wikipedia 기사 의 정확도 섹션을 참조하십시오 . 마지막으로, 기계 수준에서 부동 소수점 숫자 / 연산에 대해 심층적이고 수학적인 토론을 원한다면 자주 인용되는 기사 모든 컴퓨터 과학자가 부동 소수점 산술에 대해 알아야 할 내용을 읽어보십시오 .
답변
부동 소수점 유형을 사용하면 이점을 얻을 수 있습니다. 나는 모든 경우에 소수점을 설계하는 경향이 있으며 프로파일 러를 사용하여 소수점에 대한 작업으로 병목 현상이 발생하거나 속도가 느려지는지 알려줍니다. 이 경우, “다운 캐스트”를 두 번 또는 부동으로 내릴 수 있지만 내부적으로 만 수행하고 수행되는 수학 연산에서 유효 자릿수를 제한하여 정밀 손실을 신중하게 관리하려고합니다.
일반적으로 값이 일시적인 경우 (재사용되지 않는 경우) 부동 소수점 유형을 사용하는 것이 안전합니다. 부동 소수점 유형의 실제 문제점은 다음 세 가지 시나리오입니다.
- 부동 소수점 값을 집계하는 중입니다 (이 경우 정밀도 오류가 복합 됨)
- 부동 소수점 값을 기반으로 값을 작성합니다 (예 : 재귀 알고리즘)
- 당신은 유효 숫자의 매우 넓은 숫자와 수학을하고있다 (예를 들어
123456789.1 * .000000000000000987654321
)
편집하다
진수 키워드는 128 비트의 데이터 타입을 나타낸다. 부동 소수점 유형과 비교할 때 10 진수 유형은 정밀도와 범위가 작기 때문에 재무 및 금전적 계산에 적합합니다.
위의 진술을 명확히하기 위해 :
나는 모든 경우에 소수점을 설계하는 경향이 있으며 프로파일 러를 사용하여 소수점에 대한 작업으로 병목 현상이 발생하거나 속도가 느려지는지 알려줍니다.
나는 소수가 유리한 산업에서만 일했습니다. 물리학 또는 그래픽 엔진을 사용하는 경우 부동 소수점 유형 (float 또는 double)을 설계하는 것이 훨씬 유리할 것입니다.
십진법은 무한정 정확하지 않지만 (원시 데이터 유형에서 비 적분에 대해 무한 정밀도를 나타내는 것은 불가능합니다), 이중보다 훨씬 더 정확합니다.
- 십진수 = 28-29 유효 숫자
- 두자리 수 = 15-16 자리
- float = 유효 숫자 7
편집 2
에 대한 응답으로 콘라드 루돌프 의 코멘트, 항목 # 1 (위) 확실히 맞습니다. 부정확 한 집계는 실제로 복잡합니다. 예제는 아래 코드를 참조하십시오.
private const float THREE_FIFTHS = 3f / 5f;
private const int ONE_MILLION = 1000000;
public static void Main(string[] args)
{
Console.WriteLine("Three Fifths: {0}", THREE_FIFTHS.ToString("F10"));
float asSingle = 0f;
double asDouble = 0d;
decimal asDecimal = 0M;
for (int i = 0; i < ONE_MILLION; i++)
{
asSingle += THREE_FIFTHS;
asDouble += THREE_FIFTHS;
asDecimal += (decimal) THREE_FIFTHS;
}
Console.WriteLine("Six Hundred Thousand: {0:F10}", THREE_FIFTHS * ONE_MILLION);
Console.WriteLine("Single: {0}", asSingle.ToString("F10"));
Console.WriteLine("Double: {0}", asDouble.ToString("F10"));
Console.WriteLine("Decimal: {0}", asDecimal.ToString("F10"));
Console.ReadLine();
}
이것은 다음을 출력합니다 :
Three Fifths: 0.6000000000
Six Hundred Thousand: 600000.0000000000
Single: 599093.4000000000
Double: 599999.9999886850
Decimal: 600000.0000000000
보시다시피, 동일한 소스 상수에서 추가하더라도 더블의 결과는 정확하지 않지만 (올바르게 반올림하지만) 플로트는 정확도가 떨어집니다. 유효 숫자 2 자리
답변
다른 사람들이 제안한 것처럼 기본 10 값 (예 : 재무 계산)에는 10 진수를 사용하십시오.
그러나 임의 계산 값의 경우 일반적으로 double이 더 정확합니다.
예를 들어, 포트폴리오에서 각 라인의 가중치를 계산하려면 결과가 거의 100 %까지 증가하므로 double을 사용하십시오.
다음 예제에서 doubleResult는 decimalResult보다 1에 가깝습니다.
// Add one third + one third + one third with decimal
decimal decimalValue = 1M / 3M;
decimal decimalResult = decimalValue + decimalValue + decimalValue;
// Add one third + one third + one third with double
double doubleValue = 1D / 3D;
double doubleResult = doubleValue + doubleValue + doubleValue;
포트폴리오의 예를 다시 살펴 보겠습니다.
-
포트폴리오의 각 라인의 시장 가치는 금전적 가치이며 아마도 10 진수로 표현하는 것이 가장 좋습니다.
-
포트폴리오의 각 라인의 가중치 (= 시장 가치 / SUM (시장 가치))는 일반적으로 이중으로 표시하는 것이 좋습니다.
답변
예를 들어 필자가 작성한 플랫 포머 게임에서 플레이어 속도를 저장하기 위해 부동을 사용했습니다. 분명히 화면에 그림을 그리기 위해 Int로 반올림하기 때문에 여기서는 정밀도가 필요하지 않습니다.
답변
일부 회계에서는 정수 유형을 대신 사용하거나 함께 사용할 가능성을 고려하십시오. 예를 들어, 귀하가 운영하는 규칙은 모든 계산 결과에 소수점 이하 6 자리 이상 이월해야하며 최종 결과는 가장 가까운 페니로 반올림됩니다.
$ 100의 1/6을 계산하면 $ 16.66666666666666 …이 산출되므로 워크 시트에서 수행되는 값은 $ 16.666667이됩니다. double과 decimal은 결과를 소수점 6 자리까지 정확하게 산출해야합니다. 그러나 결과를 정수 16666667으로 전달하여 누적 오류를 피할 수 있습니다. 이후의 각 계산은 동일한 정밀도로 수행하고 유사하게 수행 할 수 있습니다. 예를 계속해서, 그 금액에 대한 텍사스 판매 세를 계산합니다 (16666667 * .0825 = 1375000). 두 개를 추가하면 (짧은 워크시 트임) 1666667 + 1375000 = 18041667. 소수점을 다시 이동하면 18.041667 또는 $ 18.04가됩니다.
이 짧은 예제는 double 또는 decimal을 사용하여 누적 오류를 생성하지는 않지만 단순히 double 또는 decimal을 계산하고 이월하면 심각한 오류가 누적되는 경우를 쉽게 보여줄 수 있습니다. 작동하는 규칙에 소수의 소수 자릿수가 필요한 경우 10 ^ (소수 자릿수 #)를 곱한 후 각 값을 정수로 저장 한 다음 10 ^ (소수 자릿수 #)로 나누어 실제 값을 구하십시오. 값은 누적 오류를 방지합니다.
동전의 일부가 발생하지 않는 상황 (예 : 자동 판매기)에서는 비 통합 유형을 전혀 사용할 이유가 없습니다. 단순히 달러가 아닌 동전을 세는 것으로 생각하십시오. 모든 계산에 전체 동전 만 포함되는 코드를 보았지만 이중을 사용하면 오류가 발생했습니다! 정수만 수학으로 문제를 제거했습니다. 따라서 가능하지 않은 두 번째와 십진수를 모두 잊어 버렸습니다.
답변
다른 언어 또는 플랫폼과 이진 삽입해야하는 경우 표준화 된 float 또는 double을 사용해야합니다.
답변
참고 :이 게시물은 http://csharpindepth.com/Articles/General/Decimal.aspx 의 10 진수 유형 기능 정보 와 그 의미에 대한 내 자신의 해석을 기반으로합니다. Double이 일반적인 IEEE 배정도라고 가정하겠습니다.
참고 2 :이 게시물에서 가장 작고 가장 큰 숫자의 수를 나타냅니다.
“소수”의 장점.
- “소수”는 (충분히 짧은) 소수로 표기 할 수있는 숫자를 정확하게 표현할 수 있으며 이중은 불가능합니다. 이것은 재무 장부에서 중요하며 결과가 계산을 수행하는 인간의 결과와 정확히 일치하는 것이 중요한 경우 유사합니다.
- “소수”는 “이중”보다 훨씬 큰 가수를가집니다. 즉, 정규화 된 범위 내의 “소수”값은 double보다 훨씬 높은 정밀도를 갖습니다.
소수의 단점
- 훨씬 느려질 것입니다 (벤치 마크는 없지만 적어도 10 배 이상 더 추측 할 것입니다). 십진수는 하드웨어 가속의 이점을 얻지 못하고 산술은 10의 거듭 제곱으로 상대적으로 비싼 곱셈 / 나눗셈이 필요합니다 ( 이는 곱셈과 나눗셈에 비해 2) 제곱에 비해 훨씬 비쌉니다.
- 십진법은 십진법보다 먼저 오버 플로우됩니다. 10 진수는 최대 ± 2 96-1 까지의 숫자 만 나타낼 수 있습니다 . 비교에 의해 double은 최대 ± 2 1024 까지의 숫자를 나타낼 수 있습니다
- 십진수가 먼저 흐릅니다. 10 진수로 표시 할 수있는 가장 작은 숫자는 ± 10-28 입니다. 비교에 의해 double은 subnromal 숫자가 지원되는 경우 2 -149 (약 10 -45 ) 까지의 값을 나타내고, 그렇지 않은 경우 2 -126 (약 10 -38 )입니다.
- 십진수는 두 배의 메모리를 두 배로 차지합니다.
내 의견은 돈 계산과 인간 계산과 정확히 일치하는 다른 경우에는 “소수”를 기본값으로 사용하고 나머지 시간에는 기본 선택으로 double을 사용해야한다는 의견입니다.