Esempio n. 1
0
        /// <summary>
        /// Add two rationals
        /// </summary>
        public static Rational32 Add(Rational32 a, Rational32 b)
        {
            // self = a/b, other = c/d

            var a_sign = a.Sign();
            var b_sign = b.Sign();

            var num = (a.Numerator64() * a_sign) * b.Denominator64();

            num += a.Denominator64() * (b.Numerator64() * b_sign);

            var den  = a.Denominator64() * b.Denominator64();
            var sign = num < 0;

            if (sign)
            {
                num = -num;
            }

            // Try to find an exact result
            var gcd = GCD(num, den);

            num /= gcd;
            den /= gcd;

            // Reduce precision until it fits
            while (num > MaxInt || WouldOverflow((uint)num, (uint)den))
            {
                gcd = GCD(num, den);
                if (gcd == 1)
                {
                    num /= 2;
                    den /= 2;
                }
                else
                {
                    num /= gcd;
                    den /= gcd;
                }
                if (den < 1)
                {
                    den = 1;
                    break;
                }
            }

            return(new Rational32(sign, (uint)num, (uint)den));
        }
Esempio n. 2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="f"></param>
        /// <returns></returns>
        public static Rational32 FromFloat(double f)
        {
            // The plan: split float into int and frac parts
            // With frac, invert and build rational. Invert that rational and add int part

            var sign = f < 0;

            if (sign)
            {
                f = -f;
            }

            var num  = (long)f;
            var frac = f - num;

            if (Math.Abs(frac) < Sigma)
            {
                return(new Rational32(sign, (uint)num, 1));                        // close enough to an integer
            }
            var top = new Rational32(sign, (uint)num, 1);
            var inv = new Rational32(sign, 1, (uint)(1 / frac));

            return(Add(top, inv));
        }