Esempio n. 1
0
        /// <summary>
        /// Convert decimal to fraction
        /// </summary>
        /// <param name="value">decimal value to convert</param>
        /// <param name="result">result fraction if conversation is succsess</param>
        /// <param name="decimalPlaces">precision of considereation frac part of value</param>
        /// <param name="trimZeroes">trim zeroes on the right part of the value or not</param>
        /// <param name="minPeriodRepeat">minimum period repeating</param>
        /// <param name="digitsForReal">precision for determination value to real if period has not been founded</param>
        /// <returns></returns>
        public static bool FromDecimal(decimal value, out Rational <T> result,
                                       int decimalPlaces = 28, bool trimZeroes = false, decimal minPeriodRepeat = 2, int digitsForReal = 9)
        {
            var valueStr = value.ToString("0.0000000000000000000000000000", CultureInfo.InvariantCulture);
            var strs     = valueStr.Split('.');

            long   intPart         = long.Parse(strs[0]);
            string fracPartTrimEnd = strs[1].TrimEnd(new char[] { '0' });
            string fracPart;

            if (trimZeroes)
            {
                fracPart      = fracPartTrimEnd;
                decimalPlaces = Math.Min(decimalPlaces, fracPart.Length);
            }
            else
            {
                fracPart = strs[1];
            }

            result = new Rational <T>();
            try
            {
                string periodPart;
                bool   periodFound = false;

                int i;
                for (i = 0; i < fracPart.Length; i++)
                {
                    if (fracPart[i] == '0' && i != 0)
                    {
                        continue;
                    }

                    for (int j = i + 1; j < fracPart.Length; j++)
                    {
                        periodPart  = fracPart.Substring(i, j - i);
                        periodFound = true;
                        decimal periodRepeat = 1;
                        decimal periodStep   = 1.0m / periodPart.Length;
                        var     upperBound   = Math.Min(fracPart.Length, decimalPlaces);
                        int     k;
                        for (k = i + periodPart.Length; k < upperBound; k += 1)
                        {
                            if (periodPart[(k - i) % periodPart.Length] != fracPart[k])
                            {
                                periodFound = false;
                                break;
                            }
                            periodRepeat += periodStep;
                        }

                        if (!periodFound && upperBound - k <= periodPart.Length && periodPart[(upperBound - i) % periodPart.Length] > '5')
                        {
                            var   ind               = (k - i) % periodPart.Length;
                            var   regroupedPeriod   = (periodPart.Substring(ind) + periodPart.Remove(ind)).Substring(0, upperBound - k);
                            ulong periodTailPlusOne = ulong.Parse(regroupedPeriod) + 1;
                            ulong fracTail          = ulong.Parse(fracPart.Substring(k, regroupedPeriod.Length));
                            if (periodTailPlusOne == fracTail)
                            {
                                periodFound = true;
                            }
                        }

                        if (periodFound && periodRepeat >= minPeriodRepeat)
                        {
                            result = FromDecimal(strs[0], fracPart.Substring(0, i), periodPart);
                            break;
                        }
                        else
                        {
                            periodFound = false;
                        }
                    }

                    if (periodFound)
                    {
                        break;
                    }
                }

                if (!periodFound)
                {
                    result = new Rational <T>(long.Parse(strs[0]), 1, false);
                    if (fracPartTrimEnd.Length != 0)
                    {
                        result += new Rational <T>(ulong.Parse(fracPartTrimEnd), TenInPower(fracPartTrimEnd.Length));
                    }
                    return(fracPartTrimEnd.Length < digitsForReal);
                }

                return(true);
            }
            catch
            {
                return(false);
            }
        }
        public ValueNode SimplifyValues(KnownFuncType?funcType, IList <ValueNode> args)
        {
            Rational <long> result;
            double          temp = 0.0;

            switch (funcType)
            {
            case KnownFuncType.Add:
                result = args[0].Value;
                for (int i = 1; i < args.Count; i++)
                {
                    result += args[i].Value;
                }
                return(new ValueNode(result));

            case KnownFuncType.Sub:
                result = args[0].Value;
                for (int i = 1; i < args.Count; i++)
                {
                    result -= args[i].Value;
                }
                return(new ValueNode(result));

            case KnownFuncType.Mult:
                result = args[0].Value;
                for (int i = 1; i < args.Count; i++)
                {
                    result *= args[i].Value;
                }
                return(new ValueNode(result));

            case KnownFuncType.Div:
                result = args[0].Value;
                for (int i = 1; i < args.Count; i++)
                {
                    result /= args[i].Value;
                }
                return(new ValueNode(result));

            case KnownFuncType.Pow:
                if (args[1].Value.ToDouble() == 0.5)
                {
                    temp = Math.Sqrt(args[0].Value.ToDouble());
                }
                else
                {
                    temp = Math.Pow(args[0].Value.ToDouble(), args[1].Value.ToDouble());
                }
                break;

            case KnownFuncType.Neg:
                return(new ValueNode(-args[0].Value));

            case KnownFuncType.Sgn:
                return(new ValueNode(new Rational <long>((long)Math.Sign(args[0].DoubleValue), 1, false)));

            case KnownFuncType.Trunc:
                return(new ValueNode(new Rational <long>((long)Math.Truncate(args[0].DoubleValue), 1, false)));

            case KnownFuncType.Round:
                return(new ValueNode(new Rational <long>((long)Math.Round(args[0].DoubleValue), 1, false)));

            case KnownFuncType.Diff:
                return(new ValueNode(0));

            case KnownFuncType.Sqrt:
                temp = Math.Sqrt(args[0].DoubleValue);
                break;

            case KnownFuncType.Sin:
                temp = Math.Sin(args[0].DoubleValue);
                break;

            case KnownFuncType.Cos:
                temp = Math.Cos(args[0].DoubleValue);
                break;

            case KnownFuncType.Tan:
                temp = Math.Tan(args[0].DoubleValue);
                break;

            case KnownFuncType.Cot:
                temp = 1 / Math.Tan(args[0].DoubleValue);
                break;

            case KnownFuncType.Arcsin:
                temp = Math.Asin(args[0].DoubleValue);
                break;

            case KnownFuncType.Arccos:
                temp = Math.Acos(args[0].DoubleValue);
                break;

            case KnownFuncType.Arctan:
                temp = Math.Atan(args[0].DoubleValue);
                break;

            case KnownFuncType.Arccot:
                temp = Math.PI / 2 - Math.Atan(args[0].DoubleValue);
                break;

            case KnownFuncType.Sinh:
                temp = Math.Sinh(args[0].DoubleValue);
                break;

            case KnownFuncType.Cosh:
                temp = Math.Cosh(args[0].DoubleValue);
                break;

            case KnownFuncType.Arcsinh:
                temp = Math.Log(args[0].DoubleValue + Math.Sqrt(args[0].DoubleValue * args[0].DoubleValue + 1));
                break;

            case KnownFuncType.Arcosh:
                temp = Math.Log(args[0].DoubleValue + Math.Sqrt(args[0].DoubleValue * args[0].DoubleValue - 1));
                break;

            case KnownFuncType.Exp:
                temp = Math.Exp(args[0].DoubleValue);
                break;

            case KnownFuncType.Ln:
                temp = Math.Log(args[0].DoubleValue);
                break;

            case KnownFuncType.Log10:
                temp = Math.Log10(args[0].DoubleValue);
                break;

            case KnownFuncType.Log:
                temp = Math.Log(args[0].DoubleValue, args[1].DoubleValue);
                break;

            case KnownFuncType.Abs:
                temp = Math.Abs(args[0].DoubleValue);
                break;

            default:
                return(null);
            }

            try
            {
                if (Rational <long> .FromDecimal((decimal)temp, out result, 14, false, 4, 8))
                {
                    return(new ValueNode(result));
                }
            }
            catch
            {
            }

            return(null);
        }
Esempio n. 3
0
 public CalculatedNode(Rational <long> value)
 {
     _value = (double)value.ToDecimal(CultureInfo.InvariantCulture);
     Name   = _value.ToString(CultureInfo.InvariantCulture);
 }
Esempio n. 4
0
        private MathFuncNode MultValues(MathFuncNode funcNode)
        {
            var values = funcNode.Children
                         .Where(child => child is ValueNode)
                         .Cast <ValueNode>()
                         .Select(valueChild => valueChild.Value);

            values = values.Concat(funcNode.Children
                                   .Where(child => child is FuncNode childFuncNode && childFuncNode.FunctionType == KnownFuncType.Neg)
                                   .Select(valueChild => new Rational <long>(-1, 1)));

            Rational <long> result = 1;

            foreach (var value in values)
            {
                result *= value;
            }

            if (result == 0)
            {
                return(new ValueNode(0));
            }

            var notValuesNodes = funcNode.Children
                                 .Where(child => !(child is ValueNode) && !(child is FuncNode childFuncNode && childFuncNode.FunctionType == KnownFuncType.Neg))
                                 .Concat(funcNode.Children
                                         .Where(child => child is FuncNode childFuncNode && childFuncNode.FunctionType == KnownFuncType.Neg)
                                         .Select(negChild => negChild.Children[0])).ToList();

            if (result == 1)
            {
                return(notValuesNodes.Count == 0 ? new ValueNode(1) :
                       notValuesNodes.Count == 1 ? notValuesNodes.First() :
                       new FuncNode(KnownFuncType.Mult, notValuesNodes));
            }
            else if (result == -1)
            {
                return(notValuesNodes.Count == 0 ? (MathFuncNode)(new ValueNode(-1)) :
                       notValuesNodes.Count == 1 ? new FuncNode(KnownFuncType.Neg, notValuesNodes.First()) :
                       new FuncNode(KnownFuncType.Neg, new FuncNode(KnownFuncType.Mult, notValuesNodes)));
            }
            else
            {
                if (notValuesNodes.Count == 0)
                {
                    return(new ValueNode(result));
                }
                else
                {
                    if (result < 0)
                    {
                        notValuesNodes.Add(new ValueNode(-result));
                        return(new FuncNode(KnownFuncType.Neg, new FuncNode(KnownFuncType.Mult, notValuesNodes)));
                    }
                    else
                    {
                        notValuesNodes.Add(new ValueNode(result));
                        return(new FuncNode(KnownFuncType.Mult, notValuesNodes));
                    }
                }
            }
        }