C# 소수점 반올림 관련 보조 라이브러리

응용프로그램 작성 도중 C#의 소수점 반올림 관련 코드에서 몇몇 자주 사용되는 기능들을 보완하는 코드를 작성하여 올려봅니다. 이 코드는 http://www.latiumsoftware.com/en/delphi/00033.php 의 코드를 바탕으로 작성된 것입니다.


namespace System
{
    // Original Source: http://www.latiumsoftware.com/en/delphi/00033.php
    public static class MathExtension
    {
        public static int Sign(
#if CS3
            this
#endif // CS3
            decimal x)
        {
            return Math.Sign(x);
        }


        public static int Sign(
#if CS3
            this
#endif // CS3
            double x)
        {
            return Math.Sign(x);
        }


        public static int Integer(
#if CS3
            this
#endif // CS3
            decimal x)
        {
            return (int)Math.Truncate(x);
        }


        public static int Integer(
#if CS3
            this
#endif // CS3
            double x)
        {
            return (int)Math.Truncate(x);
        }


        public static decimal Fraction(
#if CS3
            this
#endif // CS3
            decimal x)
        {
            return x – Math.Truncate(x);
        }


        public static double Fraction(
#if CS3
            this
#endif // CS3
            double x)
        {
            return x – Math.Truncate(x);
        }


        public static decimal RoundUp(
#if CS3
            this
#endif // CS3
            decimal x)
        {
            return Integer(x) + Sign(Fraction(x));
        }


        public static double RoundUp(
#if CS3
            this
#endif // CS3
            double x)
        {
            return Integer(x) + Sign(Fraction(x));
        }


        public static decimal RoundDown(
#if CS3
            this
#endif // CS3
            decimal x)
        {
            return Integer(x);
        }


        public static double RoundDown(
#if CS3
            this
#endif // CS3
            double x)
        {
            return Integer(x);
        }


        public static decimal Round(
#if CS3
            this
#endif // CS3
            decimal x)
        {
            return Integer(x) + Integer(Fraction(x) * 2m);
        }


        public static double Round(
#if CS3
            this
#endif // CS3
            double x)
        {
            return Integer(x) + Integer(Fraction(x) * 2d);
        }


        public static decimal Fix(
#if CS3
            this
#endif // CS3
            decimal x)
        {
            if (x >= 0m || Fraction(x) == 0m)
                return Integer(x);
            else
                return Integer(x) – 1;
        }


        public static double Fix(
#if CS3
            this
#endif // CS3
            double x)
        {
            if (x >= 0d || Fraction(x) == 0d)
                return Integer(x);
            else
                return Integer(x) – 1;
        }


        public static decimal RoundDownFix(
#if CS3
            this
#endif // CS3
            decimal x)
        {
            return Fix(x);
        }


        public static double RoundDownFix(
#if CS3
            this
#endif // CS3
            double x)
        {
            return Fix(x);
        }


        public static int Absolute(
#if CS3
            this
#endif // CS3
            int x)
        {
            return Math.Abs(x);
        }


        public static decimal RoundUpFix(
#if CS3
            this
#endif // CS3
            decimal x)
        {
            return Fix(x) + Absolute(Sign(Fraction(x)));
        }


        public static double RoundUpFix(
#if CS3
            this
#endif // CS3
            double x)
        {
            return Fix(x) + Absolute(Sign(Fraction(x)));
        }


        public static decimal RoundFix(
#if CS3
            this
#endif // CS3
            decimal x)
        {
            return Fix(x + 0.5m);
        }


        public static double RoundFix(
#if CS3
            this
#endif // CS3
            double x)
        {
            return Fix(x + 0.5d);
        }


        public static decimal RoundTo(
#if CS3
            this
#endif // CS3
            decimal x, int d)
        {
            decimal n = (decimal)Math.Pow(10, d);
            x *= n;
            return (Integer(x) + Integer(Fraction(x) * 2m)) / n;
        }


        public static double RoundTo(
#if CS3
            this
#endif // CS3
            double x, int d)
        {
            double n = Math.Pow(10, d);
            x *= n;
            return (Integer(x) + Integer(Fraction(x) * 2d)) / n;
        }
    }
}


사용 예시는 다음과 같습니다.


using System;


namespace ConsoleApplication1
{
    public static class Program
    {
        [STAThread]
        public static void Main(string[] args)
        {
#if CS3
            Console.WriteLine(“{0}”, (3.3m).RoundUp() == 4m);
            Console.WriteLine(“{0}”, (-3.3m).RoundUp() == -4m);
            Console.WriteLine(“{0}”, (3.7m).RoundDown() == 3m);
            Console.WriteLine(“{0}”, (-3.7m).RoundDown() == -3m);
            Console.WriteLine(“{0}”, (3.5m).Round() == 4m);
            Console.WriteLine(“{0}”, (-3.5m).Round() == -4m);
            Console.WriteLine(“{0}”, (3.1m).Round() == 3m);
            Console.WriteLine(“{0}”, (-3.1m).Round() == -3m);
            Console.WriteLine(“{0}”, (3.7m).Integer() == 3);
            Console.WriteLine(“{0}”, (-3.7m).Integer() == -3);
            Console.WriteLine(“{0}”, (3.7m).Fix() == 3m);
            Console.WriteLine(“{0}”, (-3.7m).Fix() == -4m);
            Console.WriteLine(“{0}”, (3.7m).RoundDownFix() == 3m);
            Console.WriteLine(“{0}”, (-3.7m).RoundDownFix() == -4m);
            Console.WriteLine(“{0}”, (3.1m).RoundDownFix() == 3m);
            Console.WriteLine(“{0}”, (-3.1m).RoundDownFix() == -4m);
            Console.WriteLine(“{0}”, (3.1m).RoundUpFix() == 4m);
            Console.WriteLine(“{0}”, (-3.7m).RoundUpFix() == -3m);
            Console.WriteLine(“{0}”, (3.5m).RoundFix() == 4m);
            Console.WriteLine(“{0}”, (-3.5m).RoundFix() == -3m);
            Console.WriteLine(“{0}”, (123.456m).RoundTo(0) == 123.00m);
            Console.WriteLine(“{0}”, (123.456m).RoundTo(2) == 123.46m);
            Console.WriteLine(“{0}”, (123456m).RoundTo(-3) == 123000m);


            Console.WriteLine(“{0}”, (3.3d).RoundUp() == 4d);
            Console.WriteLine(“{0}”, (-3.3d).RoundUp() == -4d);
            Console.WriteLine(“{0}”, (3.7d).RoundDown() == 3d);
            Console.WriteLine(“{0}”, (-3.7d).RoundDown() == -3d);
            Console.WriteLine(“{0}”, (3.5d).Round() == 4d);
            Console.WriteLine(“{0}”, (-3.5d).Round() == -4d);
            Console.WriteLine(“{0}”, (3.1d).Round() == 3d);
            Console.WriteLine(“{0}”, (-3.1d).Round() == -3d);
            Console.WriteLine(“{0}”, (3.7d).Integer() == 3);
            Console.WriteLine(“{0}”, (-3.7d).Integer() == -3);
            Console.WriteLine(“{0}”, (3.7d).Fix() == 3d);
            Console.WriteLine(“{0}”, (-3.7d).Fix() == -4d);
            Console.WriteLine(“{0}”, (3.7d).RoundDownFix() == 3d);
            Console.WriteLine(“{0}”, (-3.7d).RoundDownFix() == -4d);
            Console.WriteLine(“{0}”, (3.1d).RoundDownFix() == 3d);
            Console.WriteLine(“{0}”, (-3.1d).RoundDownFix() == -4d);
            Console.WriteLine(“{0}”, (3.1d).RoundUpFix() == 4d);
            Console.WriteLine(“{0}”, (-3.7d).RoundUpFix() == -3d);
            Console.WriteLine(“{0}”, (3.5d).RoundFix() == 4d);
            Console.WriteLine(“{0}”, (-3.5d).RoundFix() == -3d);
            Console.WriteLine(“{0}”, (123.456d).RoundTo(0) == 123.00d);
            Console.WriteLine(“{0}”, (123.456d).RoundTo(2) == 123.46d);
            Console.WriteLine(“{0}”, (123456d).RoundTo(-3) == 123000d);
#else // !CS3
            Console.WriteLine(“{0}”, MathExtension.RoundUp(3.3m) == 4m);
            Console.WriteLine(“{0}”, MathExtension.RoundUp(-3.3m) == -4m);
            Console.WriteLine(“{0}”, MathExtension.RoundDown(3.7m) == 3m);
            Console.WriteLine(“{0}”, MathExtension.RoundDown(-3.7m) == -3m);
            Console.WriteLine(“{0}”, MathExtension.Round(3.5m) == 4m);
            Console.WriteLine(“{0}”, MathExtension.Round(-3.5m) == -4m);
            Console.WriteLine(“{0}”, MathExtension.Round(3.1m) == 3m);
            Console.WriteLine(“{0}”, MathExtension.Round(-3.1m) == -3m);
            Console.WriteLine(“{0}”, MathExtension.Integer(3.7m) == 3);
            Console.WriteLine(“{0}”, MathExtension.Integer(-3.7m) == -3);
            Console.WriteLine(“{0}”, MathExtension.Fix(3.7m) == 3);
            Console.WriteLine(“{0}”, MathExtension.Fix(-3.7m) == -4);
            Console.WriteLine(“{0}”, MathExtension.RoundDownFix(3.7m) == 3m);
            Console.WriteLine(“{0}”, MathExtension.RoundDownFix(-3.7m) == -4m);
            Console.WriteLine(“{0}”, MathExtension.RoundDownFix(3.1m) == 3m);
            Console.WriteLine(“{0}”, MathExtension.RoundDownFix(-3.1m) == -4m);
            Console.WriteLine(“{0}”, MathExtension.RoundUpFix(3.1m) == 4m);
            Console.WriteLine(“{0}”, MathExtension.RoundUpFix(-3.7m) == -3m);
            Console.WriteLine(“{0}”, MathExtension.RoundFix(3.5m) == 4m);
            Console.WriteLine(“{0}”, MathExtension.RoundFix(-3.5m) == -3m);
            Console.WriteLine(“{0}”, MathExtension.RoundTo(123.456m, 0) == 123.00m);
            Console.WriteLine(“{0}”, MathExtension.RoundTo(123.456m, 2) == 123.46m);
            Console.WriteLine(“{0}”, MathExtension.RoundTo(123456m, -3) == 123000m);


            Console.WriteLine(“{0}”, MathExtension.RoundUp(3.3d) == 4d);
            Console.WriteLine(“{0}”, MathExtension.RoundUp(-3.3d) == -4d);
            Console.WriteLine(“{0}”, MathExtension.RoundDown(3.7d) == 3d);
            Console.WriteLine(“{0}”, MathExtension.RoundDown(-3.7d) == -3d);
            Console.WriteLine(“{0}”, MathExtension.Round(3.5d) == 4d);
            Console.WriteLine(“{0}”, MathExtension.Round(-3.5d) == -4d);
            Console.WriteLine(“{0}”, MathExtension.Round(3.1d) == 3d);
            Console.WriteLine(“{0}”, MathExtension.Round(-3.1d) == -3d);
            Console.WriteLine(“{0}”, MathExtension.Integer(3.7d) == 3);
            Console.WriteLine(“{0}”, MathExtension.Integer(-3.7d) == -3);
            Console.WriteLine(“{0}”, MathExtension.Fix(3.7d) == 3);
            Console.WriteLine(“{0}”, MathExtension.Fix(-3.7d) == -4);
            Console.WriteLine(“{0}”, MathExtension.RoundDownFix(3.7d) == 3d);
            Console.WriteLine(“{0}”, MathExtension.RoundDownFix(-3.7d) == -4d);
            Console.WriteLine(“{0}”, MathExtension.RoundDownFix(3.1d) == 3d);
            Console.WriteLine(“{0}”, MathExtension.RoundDownFix(-3.1d) == -4d);
            Console.WriteLine(“{0}”, MathExtension.RoundUpFix(3.1d) == 4d);
            Console.WriteLine(“{0}”, MathExtension.RoundUpFix(-3.7d) == -3d);
            Console.WriteLine(“{0}”, MathExtension.RoundFix(3.5d) == 4d);
            Console.WriteLine(“{0}”, MathExtension.RoundFix(-3.5d) == -3d);
            Console.WriteLine(“{0}”, MathExtension.RoundTo(123.456d, 0) == 123.00d);
            Console.WriteLine(“{0}”, MathExtension.RoundTo(123.456d, 2) == 123.46d);
            Console.WriteLine(“{0}”, MathExtension.RoundTo(123456d, -3) == 123000d);
#endif // CS3
        }
    }
}


위의 코드에서 CS3 라는 매크로를 프로젝트 내에 설정하면 Extension Method로 사용할 수 있으며, 이 매크로의 선언을 해제하면 일반 정적 메서드로 변경하여 사용할 수 있습니다. 여러 메서드들이 있지만 그 중에서도 RoundTo 메서드는 사용 빈도가 매우 많은 함수일 듯 합니다. 🙂

댓글 남기기