'2009/01/04'에 해당되는 글 1건

  1. 2009/01/04 [C#] Fraction

floating-point arithmetic의 오차 때문에, 누적시킬수록 오차가 커지는 문제를 해결하기 위하여 작성해 보았습니다. Value-type이므로 편하게 쓰시면 됩니다.

    struct Fraction
    {       
        private int numerator;
        private int denominator;

        public int Numerator { get { return numerator; } }
        public int Denominator { get { return denominator; } }

        public Fraction(int num) : this()
        {
            this.SetValue(num);
        }

        public Fraction(int numerator, int denominator) : this()
        {
            this.SetValue(numerator, denominator);           
        }

        // note that the change is irreversible.
        public static implicit operator float(Fraction f)
        {
            return (float)f.numerator / f.denominator;
        }

        public static implicit operator double(Fraction f)
        {
            return (double)f.numerator / f.denominator;
        }

        public static implicit operator Fraction(int i)
        {
            return new Fraction(i);
        }

        public static Fraction operator +(Fraction a, Fraction b)
        {
            return new Fraction(
                a.numerator * b.denominator + b.numerator * a.denominator,
                a.denominator * b.denominator);
        }

        public static Fraction operator -(Fraction a, Fraction b)
        {
            return new Fraction(
                a.numerator * b.denominator - b.numerator * a.denominator,
                a.denominator * b.denominator);
        }

        public static Fraction operator *(Fraction a, Fraction b)
        {
            return new Fraction(
                a.numerator * b.numerator,
                a.denominator * b.denominator);
        }

        public static Fraction operator /(Fraction a, Fraction b)
        {
            return new Fraction(
                a.numerator * b.denominator,
                a.denominator * b.numerator);
        }

        public void SetValue(int num)
        {
            this.numerator = num;
            this.denominator = 1;
        }

        public void SetValue(int numerator, int denominator)
        {
            this.numerator = numerator;
            this.denominator = denominator;

            Reduce();
        }

        private void Reduce()
        {
            // get GCD with Euclidean algorithm
            int a = Math.Abs(this.numerator);
            int b = Math.Abs(this.denominator);
            int temp;

            while (b != 0)
            {
                temp = a % b;
                a = b;                 
                b = temp;
            }

            this.numerator /= a;
            this.denominator /= a;
        }

        public Fraction Reciprocal()
        {
            return new Fraction(denominator, numerator);
        }

        public override string ToString()
        {
            double value = this;
            if (value == (int)value)
                return ""+value;

            return numerator+"/"+denominator;
        }

크리에이티브 커먼즈 라이센스
Creative Commons License
2009/01/04 23:27 2009/01/04 23:27

댓글을 달아 주세요