문제

사용하면 세 가지 장점을 들 수 있습니다. double (또는 float) 대신에 decimal:

  1. 메모리를 덜 사용합니다.
  2. 부동 소수점 수학 연산은 프로세서에서 기본적으로 지원되므로 더 빠릅니다.
  3. 더 넓은 범위의 숫자를 나타낼 수 있습니다.

그러나 이러한 장점은 모델링 소프트웨어에서 볼 수 있는 것과 같이 계산 집약적인 작업에만 적용되는 것 같습니다.물론 재무 계산과 같이 정밀도가 필요한 경우에는 복식을 사용해서는 안 됩니다.그럼 선택해야 할 실질적인 이유가 있나요? double (또는 float) 대신에 decimal "정상적인" 응용 프로그램에서는?

다음을 추가하도록 편집되었습니다.모든 훌륭한 답변에 감사드립니다. 나는 그들로부터 배웠습니다.

추가 질문:몇몇 사람들은 double이 실수를 더 정확하게 나타낼 수 있다는 점을 지적했습니다.선언되면 일반적으로 더 정확하게 표현한다고 생각합니다.하지만 부동 소수점 연산을 수행하면 정확도가 (때로는 상당히) 감소할 수 있다는 것이 사실입니까?

도움이 되었습니까?

해결책

나는 당신이 장점을 아주 잘 요약했다고 생각합니다. 그러나 당신은 한 점이 누락되었습니다. 그만큼 decimal 유형은 표현에서 더 정확합니다 베이스 10 숫자 (예 : 통화/재무 계산에 사용되는 숫자). 일반적으로 double 유형은 적어도 큰 정밀도 (누군가가 내가 틀렸을 때 나를 교정하고) 임의의 실수에 대한 더 큰 속도를 제공 할 것입니다. 간단한 결론은 다음과 같은 것입니다. 사용해야 할 곳을 고려할 때 항상 사용하십시오. double 필요하지 않는 한 base 10 정확도 decimal 제안.

편집하다:

작업 후 부동 소수점 수의 정확도 감소에 대한 추가 질문과 관련하여 이는 약간 더 미묘한 문제입니다. 실제로, 정밀도 (여기서 정확도를 위해 상호 교환 적으로 사용)는 각 작업이 수행 된 후 꾸준히 감소합니다. 이것은 두 가지 이유 때문입니다.

  1. 특정 숫자 (가장 분명하게 소수)를 부동 소수점 형태로 표현할 수 없다는 사실
  2. 마치 손으로 계산하는 것처럼 반올림 오류가 발생합니다. 그러나 이러한 오류가 많은 생각을 보장 할만 큼 중요한지 여부는 컨텍스트 (수행중인 운영 수)에 크게 의존합니다.

모든 경우에, 이론적으로 동등한 두 개의 부동 소수점 숫자를 비교하려면 (그러나 다른 계산을 사용하여 도착한 경우) 어느 정도의 공차를 허용해야합니다 (얼마나 많은 양이지만 일반적으로 매우 작음) .

정확도의 오류가 소개 될 수있는 특정 사례에 대한 자세한 개요는 위키 백과 기사. 마지막으로, 기계 수준에서 부동 소수점 번호/작업에 대한 심각한 심층적 인 (및 수학적) 토론을 원한다면 종종 인용 된 기사를 읽으십시오. 모든 컴퓨터 과학자가 부동 소수점 산술에 대해 알아야 할 것.

다른 팁

부동 소수점 유형을 사용하면 이점이있는 것 같습니다. 나는 모든 경우에 소수성을 설계하는 경향이 있으며, 프로파일 러에 의존하여 소수점에서의 작업이 병목 현상 또는 속도를 유발하는지 알려줍니다. 그러한 경우, 나는 "캐스트"를 두 배로 또는 부유하게 만들지 만 내부적으로 만 수행하고 수행중인 수학적 작동의 중요한 숫자 수를 제한하여 정밀 손실을 신중하게 관리하려고 노력합니다.

일반적으로 값이 과도 (재사용되지 않음) 인 경우 부동 소수점 유형을 사용하는 것이 안전합니다. 부동 소수점 유형의 실제 문제는 다음 세 가지 시나리오입니다.

  1. 부동 소수점 값을 집계하고 있습니다 (이 경우 정밀 오류 화합물)
  2. 부동 소수점 값을 기준으로 값을 만듭니다 (예 : 재귀 알고리즘).
  3. 당신은 매우 많은 수의 중요한 숫자로 수학을하고 있습니다 (예 : 123456789.1 * .000000000000000987654321)

편집하다

에 따르면 c# decimals에 대한 참조 문서:

그만큼 소수 키워드는 128 비트 데이터 유형을 나타냅니다. 부동 소수점 유형에 비해 소수점 유형은 정밀도와 더 작은 범위를 가지므로 재무 및 금전적 계산에 적합합니다.

위의 진술을 명확히하기 위해 :

나는 모든 경우에 소수성을 설계하는 경향이 있으며, 프로파일 러에 의존하여 소수점에서의 작업이 병목 현상 또는 속도를 유발하는지 알려줍니다.

나는 소마가 유리한 산업에서만 일한 적이 있습니다. phsyics 또는 그래픽 엔진에서 작업하는 경우 부동 소수점 유형 (플로트 또는 이중)을 위해 설계하는 것이 훨씬 더 유리할 것입니다.

소수점은 무한히 정확하지 않지만 (원시 데이터 유형에서 비 통신에 대한 무한 정밀도를 나타내는 것은 불가능하지만) 이중보다 훨씬 정확합니다.

  • 10 진수 = 28-29 중요한 숫자
  • Double = 15-16 중요한 숫자
  • float = 7 중요한 숫자

편집 2

응답으로 Konrad Rudolph댓글, 항목 # 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

보시다시피, 우리가 동일한 소스 상수에서 추가하더라도 더블의 결과는 덜 정확하지만 (아마도 올바르게 둥글지만) 플로트는 훨씬 덜 정확합니다. 두 개의 중요한 숫자.

다른 사람들이 제안한대로 기본 10 값, 즉 재무 계산에는 10 진수를 사용하십시오.

그러나 더블은 일반적으로 임의의 계산 값에 대해 더 정확합니다.

예를 들어 포트폴리오에서 각 라인의 가중치를 계산하려면 결과가 최대 100%더 많이 추가되므로 두 배를 사용하십시오.

다음 예에서 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;

그래서 다시 포트폴리오의 예를 들어보세요 :

  • 포트폴리오의 각 라인의 시장 가치는 금전적 가치이며 아마도 십진수로 가장 잘 표현 될 것입니다.

  • 포트폴리오의 각 라인의 가중치 (= 시장 가치 / 합 (시장 가치))는 일반적으로 두 배로 더 잘 표현됩니다.

정밀도가 필요하지 않을 때는 double 또는 float를 사용합니다. 예를 들어 제가 작성한 플랫폼 게임에서는 float를 사용하여 플레이어 속도를 저장했습니다.분명히 화면에 그리기 위해 결국 Int로 반올림하기 때문에 여기에서는 초정밀도가 필요하지 않습니다.

일부 회계에서는 대신 또는 함께 적분 유형을 사용할 가능성을 고려하십시오. 예를 들어, 당신이 운영하는 규칙에 따라 모든 계산 결과가 최소 6 개의 소수점 이하 자리가 이월되며 최종 결과는 가장 가까운 페니로 반올림됩니다.

$ 100 $ 100의 1/6 계산은 $ 16.66666666666666 ... 따라서 워크 시트에서 수행되는 가치는 $ 16.666667입니다. 이중과 소수점은 모두 6 진수 자리로 정확하게 생성해야합니다. 그러나 결과를 정수 16666667로 전달함으로써 누적 오류를 피할 수 있습니다. 각 후속 계산은 동일한 정밀도로 이루어져서 유사하게 전달 될 수 있습니다. 예를 계속하면서, 나는 그 금액 (16666667 * .0825 = 1375000)에 대한 텍사스 판매 세를 계산합니다. 두 가지 (짧은 워크 시트) 1666667 + 1375000 = 18041667. 소수점을 되돌리면 18.041667 또는 $ 18.04를 제공합니다.

이 짧은 예제는 이중 또는 소수점을 사용하여 누적 오류를 일으키지 않지만, 단순히 이중 또는 소수점을 계산하고 앞으로 운반하는 것이 상당한 오류를 축적하는 경우를 보여주는 것이 매우 쉽습니다. 귀하가 운영하는 규칙에 제한된 수의 소수점 자리가 필요한 경우, 10^(소수점 이하)를 곱하여 각 값을 정수로 저장 한 다음 실제를 얻기 위해 10^(소수점 이하 자리의 #)로 나누어줍니다. 값은 누적 오류를 피합니다.

페니의 일부가 발생하지 않는 상황 (예 : 자동 판매기)이 발생하지 않는 경우, 비 통신 유형을 전혀 사용할 이유가 없습니다. 단순히 달러가 아닌 동전을 세는 것으로 생각하십시오. 나는 모든 계산에 전체 동전 만 포함되는 코드를 보았지만 이중을 사용하면 오류가 발생했습니다! 정수 전용 수학이 문제를 제거했습니다. 그래서 나의 비 전통적인 대답은 가능하면 이중과 소수점을 모두 포기하는 것입니다.

다른 언어 나 플랫폼과 인트롭을 바이너리에 바이너링 해야하는 경우 표준화 된 Float 또는 Double을 사용해야 할 수도 있습니다.

참고 :이 게시물은 10 진수 유형의 기능을 기반으로합니다. http://csharpindepth.com/articles/general/decimal.aspx 그리고 그것이 무엇을 의미하는지에 대한 나의 해석. 이중은 정상적인 IEEE 이중 정밀도라고 가정합니다.

참고 2 :이 게시물에서 가장 작고 가장 큰 수의 크기.

"소수"의 장점.

  • "Decimal"은 (충분히 짧은) 소수점 분수로 작성할 수있는 정확한 숫자를 나타낼 수 있습니다. 이것은 금융 원장에서 중요하며 결과가 계산을 수행하는 인간이 정확히 일치하는 것이 중요합니다.
  • "Decimal"은 "Double"보다 훨씬 큰 Mantissa를 가지고 있습니다. 즉, 정규화 된 범위의 "소수"는 이중보다 훨씬 높은 정밀도를 갖게됩니다.

소수점의 단점

  • 훨씬 느리게 될 것입니다 (벤치 마크가 없지만 적어도 크기가 더 많을 것 같아요), Decimal은 하드웨어 가속화의 혜택을받지 못하고 산술은 10의 전력에 의한 상대적으로 비싼 곱셈/분할이 필요합니다 ( 이는 2) 첨가/뺄셈 전 지수와 일치하고 곱셈/분할 후 지수를 다시 범위로 가져 오는 것보다 훨씬 비싸다.
  • 10 진수는 이중의 유언을 초기에 넘칠 것입니다. 소수점은 최대 ± 2의 숫자만을 나타낼 수 있습니다96-1 . 비교하여 Double은 거의 ± 2까지의 숫자를 나타낼 수 있습니다.1024
  • 소수점은 더 일찍 유도됩니다. 소수점으로 표시되는 가장 작은 숫자는 ± 10입니다-28 . 비교하여 더블은 2로 아래로 값을 나타낼 수 있습니다-149 (약 10-45) 하부 숫자가 지원되는 경우 2-126 (약 10-38) 그렇지 않은 경우.
  • 10 진수는 두 배의 메모리를 두 배로 늘립니다.

내 의견은 돈 노동에 "소수"를 사용하는 데 기본값과 인간 계산이 정확히 일치하는 다른 사례가 중요하고 나머지 기본 선택으로 두 배를 사용해야한다는 것입니다.

정확성보다 성능을 평가하는 경우 부동 소수점을 사용하십시오.

응용 프로그램의 기능 유형을 선택하십시오. 재무 분석에서와 같이 정밀도가 필요한 경우 질문에 답변했습니다. 그러나 응용 프로그램이 추정으로 정착 할 수있는 경우 두 배로 OK를 사용합니다.

귀하의 신청서는 빠른 계산이 필요합니까, 아니면 전 세계에서 모든 시간을 대답 할 것인가? 실제로 응용 프로그램 유형에 따라 다릅니다.

그래픽 굶주린? 플로트 또는 더블로 충분합니다. 재무 데이터 분석, 행성의 정밀도를 때리는 유성? 그것들은 약간의 정밀도가 필요할 것입니다 :)

소수점은 더 넓은 바이트를 가지며, 이중은 CPU에 의해 기본적으로 지원됩니다. 10 진수는베이스 -10이므로 소수점이 계산되는 동안 소수점에서 더 가구 전환이 발생합니다.

For accounting - decimal
For finance - double
For heavy computation - double

.NET CLR은 Math.Pow (Double, Double) 만 지원합니다. 소수점은 지원되지 않습니다.

.NET 프레임 워크 4

[SecuritySafeCritical]
public static extern double Pow(double x, double y);

이 표기법이 소수점 디스플레이보다 짧은 경우 이중 값은 기본적으로 과학 표기법으로 직렬화됩니다. (예 : .00000003은 3E-8이 될 것입니다) 소수점 값은 과학적 표기법으로 결코 직렬화되지 않습니다. 외부 당사자에 의한 소비를 직렬화 할 때, 이것은 고려할 수 있습니다.

필요한 것에 따라 다릅니다.

플로트와 더블은 당신이 가진 이진 데이터 유형이기 때문에 약간 예를 들어 라운드 숫자의 방해가되는 Diifculties 및 Errror는 예를 들어 Double이 0.1에서 0.100000001490116으로 반올림하면 Double은 1 / 3에서 0.3333334326441을 1/33333334326441로 둥글게됩니다. 단순히 모든 실수가 이중 유형으로 정확한 표현을 갖는 것은 아닙니다.

운 좋게도 C#은 소위 소수점 부동 소수점 산술을 지원하며, 여기서 숫자는 이진 시스템이 아닌 10 진수 숫자 시스템을 통해 표시됩니다. 따라서, 소수점 부동 소수점-문서 정확도를 잃지 않습니다 부동 소수점 번호를 저장 및 처리 할 때. 따라서 높은 수준의 정확도가 필요한 계산에 엄청나게 적합합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top