NGMsoftware

NGMsoftware
로그인 회원가입
  • 매뉴얼
  • 학습
  • 매뉴얼

    학습


    C# 5. Float, double, decimal 형식

    페이지 정보

    본문

    Float 형식은 32비트 Double 형식은 64비트 부동 소수점 값을 저장하는 단순 형식을 나타냅니다. Decimal 형식은 128비트 데이터 형식을 나타냅니다. Decimal은 부동 소수점 형식에 비해 전체 자릿수는 크고 범위는 작아서 재무 및 통화 계산에 적합합니다. Decimal은 부동 소수점 형식간의 암시적 변환을 제공하지 않습니다. 따라서, Decimal에서 부동 소수점 형식으로 변환하려면 명시적 케스팅을 해야 합니다.

     

    기본적으로 할당 연산자의 오른쪽에 있는 실수형 숫자 리터럴은 double로 처리됩니다. 그렇기 때문에 float, decimal같은 경우에는 접미사를 붙여줘야 합니다. 아래는 각 형식에 대해 접미사를 사용하는 방법을 보여줍니다.

    using System;
    using System.Collections.Generic;
    using System.Text;
     
    namespace HelloCsharp
    {
        class Program
        {
            static void Main(string[] args)
            {
                float floatType = 1.0f;
                double doubleType = 1.0d; // double은 접미사인 d 생략 가능            
                decimal decimalType = 1.0m;
                Console.WriteLine(floatType);
                Console.WriteLine(doubleType);
                Console.WriteLine(decimalType);
                Console.ReadLine();
            }
        }
    }
    

     

     

    이 코드를 실행해 보면 아래와 같습니다.

    dTPxgGl.png

     

     

    코드를 아래와 같이 수정한 후 다시 실행해 봅니다.

    using System;
    using System.Collections.Generic;
    using System.Text;
     
    namespace HelloCsharp
    {
        class Program
        {
            static void Main(string[] args)
            {
                float floatType = 1.0f / 3;
                double doubleType = 1.0d / 3; // double은 접미사인 d 생략 가능
                decimal decimalType = 1.0m / 3;
                Console.WriteLine(floatType);
                Console.WriteLine(doubleType);
                Console.WriteLine(decimalType);
                Console.ReadLine();
            }
        }
    }

     

     

    이 코드를 실행하면 아래와 같습니다. float는 소수점 7자리, double은 소수점 15자리, decimal은 28자리를 표현할 수 있습니다.

    6beDJKR.png

     

     

    다음과 같이 코드를 변경한 후 확인해 봅시다. 라인 11~13의 소수점을 제거한 후 실행합니다. 위와 똑같은 결과를 얻을 수 있습니다.

    using System;
    using System.Collections.Generic;
    using System.Text;
     
    namespace HelloCsharp
    {
        class Program
        {
            static void Main(string[] args)
            {
                float floatType = 1f / 3;
                double doubleType = 1d / 3; // double은 접미사인 d 생략 가능
                decimal decimalType = 1m / 3;
                Console.WriteLine(floatType);
                Console.WriteLine(doubleType);
                Console.WriteLine(decimalType);
                Console.ReadLine();
            }
        }
    }

     

     

    그렇다면 double의 경우 접미사를 생략하면 어떻게 될까요? 위의 코드에서 12라인의 접미사 d를 지우고 실행해 봅니다. 정수로 변환되고 소수점 이하는 버림이 된것을 확인할 수 있습니다. 흔히 하는 실수로 가급적이면 명시적으로 접미사를 붙여주는게 좋습니다. 복잡한 수식에서 이러한 버그는 찾기도 어렵고 시간을 많이 소모하게 됩니다.

    B8MLi3K.png

     

     

    그럼 12라인을 다음과 같이 수정합니다.

    double doubleType = 1.0 / 3;

     

    실행해 보면 정상적으로 동작하는것을 확인할 수 있습니다.

    2nQ6yE5.png

     

     

    Decimal은 아주 높은 정밀도를 가지고 있으며 통상 고도의 정확성을 필요로 하는 금융, 우주, 항공 관련 어플리케이션에서 사용됩니다. 나노 또는 마이크로 단위를 사용하는 제조쪽도 Decimal까지는 필요하지 않습니다. 보통 Float만으로도 충분하거든요. 높은 정밀도를 요구하지 않는다면 Decimal은 사용하지 않는게 좋습니다. 일부 테스트에서는 20배까지 속도 차이가 난다고도 합니다.

     

    그럼 실제로 연산의 결과를 보고 어느 정도의 정밀도(Precision)를 가지고 있는지 확인해 보도록 하겠습니다. Main 메서드의 코드를 모두 지운 후 아래의 코드로 대체한 후 실행합니다.

    using System;
    using System.Collections.Generic;
    using System.Text;
     
    namespace HelloCsharp
    {
        class Program
        {
            static void Main(string[] args)
            {
                float a = 69.6875f;
                Console.WriteLine("a : {0}", a);
                double b = (double)a;
                Console.WriteLine("b : {0}", b);
                Console.WriteLine("69.6875 == b : {0}", 69.6875 == b);
                float x = 0.1f;
                Console.WriteLine("x : {0}", x);
                double y = (double)x;
                Console.WriteLine("y : {0}", y);
                Console.WriteLine("0.1 == y : {0}", 0.1 == y);
                Console.ReadLine();
            }
        }
    }
    

     

     

    실행해 보면 다소 엉뚱한 결과를 얻을 수 있는데요. 이러한 현상은 IEEE(전기 전자 기술자 협회) 754 표준을 사용하는 모든 컴퓨터에서 발생되는 문제입니다. 부동 소수점을 표현하는 가장 널리 쓰이는 표준이기는 하나 정확하게 부동 소수점을 표현할 수는 없습니다. 강제적인 사항은 단정도(Single precision)와 배정도(double precision)이며 128비트는 선택사항으로 되어 있습니다. 다행히도 C#에서는 128비트인 Decimal이 정의되어 있습니다.

    XbBLxGD.png

     

     

    위와 같은 결과가 나오게 된 원인은 단정도(C#에서의 float)는 4바이트(32비트)로 10진수 값을 2진수로 바꾸면서 발생되는 Round off(반올림) 현상입니다. 2진수로 처리하다 보면 8바이트에 다 담을 수 없기에 마지막에 반올림하여 근사값으로 처리하게 됩니다. 만약 모두 담을 수 있는 수라면 문제 없겠지만요. 따라서 배정도(C#에서의 double) 8바이트(64비트)로 좀 더 근사값을 표시할 수 있게됩니다. (자료형이 크므로...)

     

    위의 코드를 다시 아래와 같이 변경한 후 실행해 보세요.

    using System;
    using System.Collections.Generic;
    using System.Text;
     
    namespace HelloCsharp
    {
        class Program
        {
            static void Main(string[] args)
            {
                float a = 69.6875f;
                Console.WriteLine("a : {0}", a);
                double b = (double)a;
                Console.WriteLine("b : {0}", b);
                Console.WriteLine("69.6875 == b : {0}", 69.6875 == b);
                decimal x = 0.1m;
                Console.WriteLine("x : {0}", x);
                double y = (double)x;
                Console.WriteLine("y : {0}", y);
                Console.WriteLine("0.1 == y : {0}", 0.1 == y);
                Console.ReadLine();
            }
        }
    }

     

     

    실행해 보면 이제 True를 출력하는 것을 확인할 수 있습니다. 혹시라도 높은 정밀도가 요구되는 연산이나 좌표계를 가지고 있다면 float는 피해야 합니다. 부동 소수점값을 이용해서 좌표를 찾아가는 로직이라면 누락될 가능성도 존재하니까요. 

     

    마지막으로...

    그렇다면 실수를 정수로 변환하면 어떤 결과를 얻을 수 있는지 확인해 봅니다. Main의 코드를 삭제하고 아래의 코드로 대체하세요.

    using System;
    using System.Collections.Generic;
    using System.Text;
     
    namespace HelloCsharp
    {
        class Program
        {
            static void Main(string[] args)
            {
                float a = 0.9f;
                int b = (int)a;
                Console.WriteLine(b);
                float c = 1.1f;
                int d = (int)c;
                Console.WriteLine(d);
                Console.ReadLine();
            }
        }
    }
    

     

     

    실행한 결과 화면입니다. 정수로 변환할 때는 소수점 이하는 모두 버림으로 처리되는 것을 확인할 수 있습니다.

    CL4Jvaj.png

     

     

    다음 시간에...

    • 네이버 공유하기
    • 페이스북 공유하기
    • 트위터 공유하기
    • 카카오스토리 공유하기
    추천0 비추천0

    댓글목록

    등록된 댓글이 없습니다.