コード例 #1
0
        //••••••••••••••••••••••••••••••••••••••••••••••••••••••••
        public static CNumber Cos(CNumber _num)
        {
            m_res = new CNumber("0", _num);

            m_res.Value = Math.Cos(_num.ToRadians);
            return(m_res);
        }
コード例 #2
0
ファイル: CCalculator.cs プロジェクト: zendive/calc
        //••••••••••••••••••••••••••••••••••••••••••••••••••••••••
        /// <summary>
        /// Solve user expression, may throw Calc.SyntaxException,
        /// Calc.CommandException, Calc.EngineException.</summary>
        /// <param name="_sExpr">user expression</param>
        /// <param name="_Answer">user answer holder, where
        /// solved expression result is placed</param>
        public void Solve(string _sExpr, ref CNumber _Answer)
        {// void expression equals to void result
            if (_sExpr == null || _sExpr == "")
            {
                return;
            }
            _sExpr = _sExpr.Replace(" ", "").ToLower(); // simplify

            CatchCommand(_sExpr);                       // if command - execute

            // reinit & assimilate template number properties
            m_block.Init(_Answer);

            // `m_result` will like the caller answer holder and will take
            // a part in temporary calculations through `Parts_Solve` and
            // Parse_to_Blocks;
            m_result = new CNumber("0", _Answer);
            try
            {
                Parse_to_Blocks(_sExpr);
            }
            catch (ServiceException xcp)
            {
                ASSERT(false, xcp.Message, "Solve.conversion");
            }

            Parts_Solve(m_block);

            // set user answer holder and common answer registry to
            // a newly solved value
            _Answer = m_block[0].Number;
            m_reg.ANSWER.GetProperties(_Answer);
            m_reg.ANSWER = _Answer;
            return;
        }
コード例 #3
0
        /// <summary>
        /// Absolute of value `_N`
        /// </summary>
        /// <param name="_N">value to take from absolut</param>
        /// <returns></returns>
        public static CNumber Abs(CNumber _N)
        {
            m_res = new CNumber("0", _N);

            m_res.Value = Math.Abs(_N.dValue);
            return(m_res);
        }
コード例 #4
0
        //••••••••••••••••••••••••••••••••••••••••••••••••••••••••
        public static CNumber Mul(CNumber _N1, CNumber _N2)
        {
            m_res = new CNumber("0", _N1);

            m_res.Value = _N1.dValue * _N2.dValue;
            return(m_res);
        }
コード例 #5
0
        //••••••••••••••••••••••••••••••••••••••••••••••••••••••••
        /// <summary>
        /// Mod devision
        /// </summary>
        /// <param name="_N"></param>
        /// <param name="_NBase">base of mod devision</param>
        /// <returns></returns>
        public static CNumber Mod(CNumber _N, CNumber _NBase)
        {
            m_res = new CNumber("0", _N);

            m_res.Value = _N.dValue % _NBase.dValue;
            return(m_res);
        }
コード例 #6
0
        //••••••••••••••••••••••••••••••••••••••••••••••••••••••••
        public static CNumber Pow(CNumber _num, CNumber _NDegree)
        {
            m_res = new CNumber("0", _num);

            m_res.Value = Math.Pow(_num.dValue, _NDegree.dValue);
            return(m_res);
        }
コード例 #7
0
        //••••••••••••••••••••••••••••••••••••••••••••••••••••••••
        // unary minus
        public static CNumber Minus(CNumber _num)
        {
            m_res = new CNumber("0", _num);

            m_res.Value = -(_num.dValue);
            return(m_res);
        }
コード例 #8
0
        //••••••••••••••••••••••••••••••••••••••••••••••••••••••••
        /// <summary>Unary Logarithm fo base 10</summary>
        /// <param name="_num">argument</param>
        /// <returns>Returns the base 10 logarithm of a specified number</returns>
        public static CNumber Log(CNumber _num)
        {
            m_res = new CNumber("0", _num);

            m_res.Value = Math.Log10(_num.dValue);
            return(m_res);
        }
コード例 #9
0
        //••••••••••••••••••••••••••••••••••••••••••••••••••••••••
        /// <summary>
        /// Root of variable degree
        /// </summary>
        /// <param name="_NDegree">root degree</param>
        /// <param name="_N">value, root of which to be taken</param>
        /// <returns>result of variable degree</returns>
        public static CNumber Root(CNumber _NDegree, CNumber _N)
        {
            CCalculator.ASSERT((_NDegree.dValue != 0.0d)
                               , "(y)_#(x): `y` - Root degree can't be NULL.", "CMath.Root binary");
            CCalculator.ASSERT((_N.dValue >= 0.0d) || (_NDegree.dValue % 2 != 0)
                               , "(y)_#(x): `x` - Must be positive and/or `y` is even."
                               , "CMath.Root binary");

            m_res       = new CNumber("0", _N);
            m_res.Value = _N.Value;

            double X = Math.Abs(_N.dValue);

            try
            {
                m_res.Value = Math.Pow(2, Math.Log(X, 2) / _NDegree.dValue);

                // changing sign of result if root argument was negative and
                // root degree was uneven
                if (_N.dValue < 0)
                {
                    m_res.Value = -m_res.dValue;
                }
            }
            catch (OverflowException)
            {
                CCalculator.ASSERT(false, "", "");
            }

            return(m_res);
        }
コード例 #10
0
        //••••••••••••••••••••••••••••••••••••••••••••••••••••••••
        public static CNumber Sin(CNumber _num)
        {
            m_res = new CNumber("0", _num);

            // TODO: Check whenever `_num` passed here from some register
            // and TCS from GUI is applied for him.
            m_res.Value = Math.Sin(_num.ToRadians);
            return(m_res);
        }
コード例 #11
0
        //••••••••••••••••••••••••••••••••••••••••••••••••••••••••
        /// <summary>
        /// Square root (degree of 2)</summary>
        /// <param name="_N">value, root of which to be evaluated</param>
        /// <returns>result of root of degree 2</returns>
        public static CNumber Root(CNumber _N)
        {
            CCalculator.ASSERT(_N.dValue > 0.0d
                               , "#(x): x - Must be positive.", "CMath.Root unary");

            m_res = new CNumber("0", _N);

            m_res.Value = Math.Sqrt(_N.dValue);
            return(m_res);
        }
コード例 #12
0
        //••••••••••••••••••••••••••••••••••••••••••••••••••••••••
        /// <summary>
        /// Regular devision
        /// </summary>
        /// <param name="_NDividend"></param>
        /// <param name="_NDivisor"></param>
        /// <returns></returns>
        public static CNumber Div(CNumber _NDividend, CNumber _NDivisor)
        {
            m_res = new CNumber("0", _NDividend);

            CCalculator.ASSERT(_NDivisor.dValue != 0.0d
                               , "Divide by zero.", "CMath.Div");

            m_res.Value = _NDividend.dValue / _NDivisor.dValue;
            return(m_res);
        }
コード例 #13
0
        //••••••••••••••••••••••••••••••••••••••••••••••••••••••••
        public static CNumber Xor(CNumber _N1, CNumber _N2)
        {
            CCalculator.ASSERT(_N1.IsInteger && _N2.IsInteger
                               , "\"XOR\" operation need integer.", "CMath.Xor");

            m_res = new CNumber("0", _N1);

            m_res.Value = (long)_N1.Value ^ (long)_N2.Value;
            return(m_res);
        }
コード例 #14
0
        //••••••••••••••••••••••••••••••••••••••••••••••••••••••••
        public static CNumber Not(CNumber _num)
        {
            CCalculator.ASSERT(_num.IsInteger
                               , "\"NOT\" operation need integer.", "CMath.Not");

            m_res = new CNumber("0", _num);

            m_res.Value = ~((long)_num.Value);
            return(m_res);
        }
コード例 #15
0
        public CNumber(string _sNum, CNumber _Etalon)
        {
            InitDefaults();

            m_cs   = _Etalon.m_cs;
            m_tcs  = _Etalon.m_tcs;
            m_prec = _Etalon.m_prec;

            this.FromString(_sNum);
        }
コード例 #16
0
        //••••••••••••••••••••••••••••••••••••••••••••••••••••••••
        /// <summary>Binary Logarithm of variable base</summary>
        /// <param name="_base">base</param>
        /// <param name="_num">argument</param>
        /// <returns>Returns the _sBase logarithm of a specified number</returns>
        public static CNumber Log(CNumber _base, CNumber _num)
        {
            CCalculator.ASSERT(_base.dValue >= 0
                               , "(y)Log(x): y - POSITIVE expected."
                               , "CMath.Log");

            m_res = new CNumber("0", _num);

            m_res.Value = Math.Log(_num.dValue, _base.dValue);
            return(m_res);
        }
コード例 #17
0
        /// <summary>Binary. Find the grat common devisor of two
        /// integer numbers</summary>
        static public CNumber GCD(CNumber _n1, CNumber _n2)
        {
            CCalculator.ASSERT(_n1.IsInteger && _n2.IsInteger
                               , "(x)Gcd(y): x, y - Integers expected.", "CMath.GCD");

            m_res = new CNumber("0", _n1);

            m_res.Value = _gcd(_n1.lValue, _n2.lValue);

            return(m_res);
        }
コード例 #18
0
ファイル: CBlock.cs プロジェクト: zendive/calc
        /// <summary>
        /// Replace sub-section of the current block with _Res</summary>
        /// <param name="_Res">replace by this CNumber</param>
        /// <param name="_from">from index (included)</param>
        /// <param name="_to">to index (included)</param>
        public void ReplaceWith(CNumber _Res, int _from, int _to)
        {
            // remove next
            for (int i = _from; i < _to; i++)
            {
                this.BaseRemoveAt(_from);
            }

            /** insertion in this collection is impossible,
             * use that fact what last item to remove is always the number
             * so replace that number with new result
             * (cant do it at the `_from` becose there may be an operator,
             * but to assign a number need to reset the key to null and this
             * impossible without rebuilding all collection)
             * */
            this.BaseSet(_from, _Res);
        }
コード例 #19
0
        //••••••••••••••••••••••••••••••••••••••••••••••••••••••••
        public static CNumber ShiftRight(CNumber _N, CNumber _BitNum)
        {
            CCalculator.ASSERT(_N.IsInteger && _BitNum.IsInteger
                               , "\">>\" operation need integer.", "CMath.ShiftRight");

            m_res = new CNumber("0", _N);

            try
            {
                int bitNum = Convert.ToInt32((long)_BitNum.Value);
                m_res.Value = (long)_N.Value >> bitNum;
            }
            catch (OverflowException)
            {
                CCalculator.ASSERT(false, "\"x >> Y\" - Y overflow.", "CMath.ShiftRight");
            }
            return(m_res);
        }
コード例 #20
0
        //••••••••••••••••••••••••••••••••••••••••••••••••••••••••
        public static CNumber Factorial(CNumber _num)
        {
            CCalculator.ASSERT(_num.IsInteger
                               , "\"!x\" operation need integer.", "CMath.Factorial");

            m_res = new CNumber("0", _num);
            if ((long)_num.Value == 0)
            {
                m_res.Value = 1L;
                return(m_res);
            }

            try
            {
                if (_num.dValue <= 20)
                {
                    long num  = (long)_num.Value;
                    long fact = num;
                    while (num > 1)
                    {
                        fact *= --num;
                    }
                    m_res.Value = fact;
                }
                else
                {
                    double num  = _num.dValue;
                    double fact = num;
                    while (num > 1)
                    {
                        fact *= --num;
                    }
                    m_res.Value = fact;
                }
            }
            catch (OverflowException)
            {
                CCalculator.ASSERT(false
                                   , "Result is out of range.", "CMath.Factorial");
            }
            return(m_res);
        }
コード例 #21
0
ファイル: CBlock.cs プロジェクト: zendive/calc
 public void AddNumber(CNumber _Number)
 {
     this.BaseAdd(null, _Number);
 }
コード例 #22
0
ファイル: CBlock.cs プロジェクト: zendive/calc
        /// <summary>
        /// Clears all the elements in the collection.</summary>
        public void Init(CNumber _Template)
        {
            this.BaseClear();

            m_NumEtalon.GetProperties(_Template);
        }
コード例 #23
0
ファイル: CBlock.cs プロジェクト: zendive/calc
 public CBlockClaster()
 {
     m_sOperator = null;
     m_Number    = null;
 }
コード例 #24
0
 /// <summary>
 /// Copy count-systems characteristics.
 /// </summary>
 /// <param name="_num">get from reference</param>
 public void GetProperties(CNumber _num)
 {
     m_cs   = _num.m_cs;
     m_tcs  = _num.m_tcs;
     m_prec = _num.m_prec;
 }
コード例 #25
0
 //••••••••••••••••••••••••••••••••••••••••••••••••••••••••
 // unarty plus
 public static CNumber Plus(CNumber _num)
 {
     return(_num);
 }
コード例 #26
0
ファイル: CCalculator.cs プロジェクト: zendive/calc
        //••••••••••••••••••••••••••••••••••••••••••••••••••••••••
        /// <summary>
        /// Solve unray operator, where operand taken from right of operator
        /// position</summary>
        /// <param name="_blocks">in blocks</param>
        /// <param name="_iHipos">at operator position</param>
        /// <returns>calculation result</returns>
        private CNumber SolveUnary(CBlock _blocks, int _iHipos)
        {
            ASSERT(((_iHipos + 1) < _blocks.Count) && (_blocks[_iHipos + 1].IsNumber)
                   , "Missing argument for >" + _blocks[_iHipos].Operator + '<'
                   , "SolveUnary");

            string  strOperator = _blocks[_iHipos].Operator;
            CNumber number      = _blocks[_iHipos + 1].Number;
            CNumber res;

            STUB(strOperator != null && strOperator != "", "Bad _sOper in SolveUnary");
            STUB(number != null, "Bad _Num in SolveUnary");

            ///-- LOGIC
            if (the(AO.NOT) == strOperator)
            {
                res = CMath.Not(number);
            }
            ///-- ARITHMETIC
            else if (the(AO.MIN) == strOperator)
            {
                res = CMath.Minus(number);
            }
            else if (the(AO.PLS) == strOperator)
            {
                res = CMath.Plus(number);
            }
            else if (the(AO.ROOT) == strOperator)
            { // square root
                res = CMath.Root(number);
            }
            else if (the(AO.ABS) == strOperator)
            {
                res = CMath.Abs(number);
            }
            ///-- THRIGONOMETRY
            else if (the(AO.SIN) == strOperator)
            {
                res = CMath.Sin(number);
            }
            else if (the(AO.COS) == strOperator)
            {
                res = CMath.Cos(number);
            }
            else if (the(AO.EXP) == strOperator)
            {
                res = CMath.Exp(number);
            }
            else if (the(AO.TAN) == strOperator)
            {
                res = CMath.Tan(number);
            }
            ///-- FUNCTION
            else if (the(AO.FACT) == strOperator)
            {
                res = CMath.Factorial(number);
            }
            else if (the(AO.LG) == strOperator)
            {
                res = CMath.Lg(number);
            }
            else if (the(AO.LN) == strOperator)
            {
                res = CMath.Ln(number);
            }
            else if (the(AO.LOG) == strOperator)
            {
                res = CMath.Log(number);
            }
            else
            {
                STUB(false, "[ " + strOperator.ToUpper()
                     + " ] not implemented unary operation!");
                return(null);
            }

            ASSERT(!(double.IsInfinity(res.dValue))
                   , "Result is ±Infinity", "SolveUnary");
            ASSERT(!(double.IsNaN(res.dValue))
                   , "Result is Not a number", "SolveUnary");

            return(res);
        }
コード例 #27
0
ファイル: CCalculator.cs プロジェクト: zendive/calc
        /// <summary>
        /// Solve binary operator, where operands taken from right and left
        /// of operator position</summary>
        /// <param name="_blocks">in blocks</param>
        /// <param name="_iHipos">at operator position</param>
        /// <returns>calculation result</returns>
        private CNumber SolveBinary(CBlock _blocks, int _iHipos)
        {
            ASSERT((_blocks.Count >= 3) && (_iHipos > 0) &&
                   ((_iHipos + 1) < _blocks.Count)
                   , "Unrecovered binary operator >" + _blocks[_iHipos].Operator + '<'
                   , "SolveBinary1");
            ASSERT(_blocks[_iHipos - 1].IsNumber && _blocks[_iHipos + 1].IsNumber
                   , "Missing argument for binary operator >" + _blocks[_iHipos].Operator + '<'
                   , "SolveBinary2");

            CNumber nLeft       = _blocks[_iHipos - 1].Number;
            string  strOperator = _blocks[_iHipos].Operator;
            CNumber nRight      = _blocks[_iHipos + 1].Number;
            CNumber res;

            STUB((nLeft != null) && (nRight != null), "Bad _nLeft in SolveBinary.");
            STUB((strOperator != null) && (strOperator != ""), "Bad _sOper in SolveBinary.");

            ///-- ARITHMETIC
            if (the(AO.POW) == strOperator)
            {
                res = CMath.Pow(nLeft, nRight);
            }
            else if (the(AO.MUL) == strOperator)
            {
                res = CMath.Mul(nLeft, nRight);
            }
            else if (the(AO.DIV) == strOperator)
            {
                res = CMath.Div(nLeft, nRight);
            }
            else if (the(AO.MOD) == strOperator)
            {
                res = CMath.Mod(nLeft, nRight);
            }
            else if (the(AO.PLS) == strOperator)
            {
                res = CMath.Plus(nLeft, nRight);
            }
            else if (the(AO.MIN) == strOperator)
            {
                res = CMath.Minus(nLeft, nRight);
            }
            else if (the(AO.ROOT) == strOperator)
            {
                res = CMath.Root(nLeft, nRight);
            }
            ///-- FUNCTION
            else if (the(AO.LOG) == strOperator)
            {
                res = CMath.Log(nLeft, nRight);
            }
            ///-- LOGIC
            else if (the(AO.AND) == strOperator)
            {
                res = CMath.Log(nLeft, nRight);
            }
            else if (the(AO.OR) == strOperator)
            {
                res = CMath.Or(nLeft, nRight);
            }
            else if (the(AO.XOR) == strOperator)
            {
                res = CMath.Xor(nLeft, nRight);
            }
            ///-- BITWISE
            else if (the(AO.SH_LEFT) == strOperator)
            {
                res = CMath.ShiftLeft(nLeft, nRight);
            }
            else if (the(AO.SH_RIGHT) == strOperator)
            {
                res = CMath.ShiftRight(nLeft, nRight);
            }
            else if (the(AO.GCD) == strOperator)
            {
                res = CMath.GCD(nLeft, nRight);
            }
            //-- not implemented
            else
            {
                STUB(false, "[" + strOperator
                     + "] not implemented binary operation!");
                return(null);
            }

            ASSERT(!(double.IsInfinity(res.dValue))
                   , "Result is ±Infinity", "SolveBinary");
            ASSERT(!(double.IsNaN(res.dValue))
                   , "Result is Not a number", "SolveBinary");

            return(res);
        }
コード例 #28
0
ファイル: CCalculator.cs プロジェクト: zendive/calc
        //••••••••••••••••••••••••••••••••••••••••••••••••••••••••
        /// <summary>
        /// Solve partitionized expression.
        /// Assume what:
        ///  - created valid partition (Parse_to_Blocks)
        ///  - any registers replaced by value (..)
        ///  - no braces conflicts (..)
        /// Parentheses solved in recursion call, end-condition is
        /// when one part is left, and its a number.</summary>
        /// <param name="_scPart">valid partition</param>
        /// <returns>answer</returns>
        private void Parts_Solve(CBlock _blocks)
        {
            int hipos = 0; // hi priority index
            int brEnd = 0; // index of found `AO.BREND`

            while (1 < _blocks.Count)
            {
                // find hi priority operator index
                if (GetHiPriorityPos(_blocks, ref hipos))
                {
                    // engage braces by self-recursion
                    if (the(AO.BRBEG) == _blocks[hipos].Operator)
                    {
                        // here `hipos` is index of `AO.BRBEG`
                        brEnd = FindEndBrace(_blocks, hipos);
                        // copy sub-expression parts
                        CBlock subBlocks = _blocks.Projection((hipos + 1), (brEnd - 1));

                        Parts_Solve(subBlocks); // enter recursion

                        // RETURN AFTER RECURSIVE CALL WITH ONLY ONE PART
                        ASSERT(1 == subBlocks.Count
                               , "Invalid recursion return"
                               , "Parts_Solve: ret from recursion");

                        _blocks.ReplaceWith(subBlocks[0].Number, hipos, brEnd);
                    }
                    /// engage unary or binary operators by priority
                    /// Check if current operator is a double-sence operator:
                    /// Unary have number from right, binary from both sides.
                    else
                    {
                        bool unary = true; // is unray by default
                        if (IsDoubleSenseAO(_blocks[hipos].Operator))
                        {
                            // check boundaries before accesing by indexes
                            if ((hipos > 0) && ((hipos + 1) < _blocks.Count))
                            {
                                // define from context...
                                unary = (_blocks[hipos - 1].IsOperator ||
                                         _blocks[hipos + 1].IsOperator);
                            }
                        }
                        else
                        {
                            // define from table of unary operators...
                            unary = IsUnaryAO(_blocks[hipos].Operator);
                        }

                        if (unary)
                        {
                            m_result = this.SolveUnary(_blocks, hipos);
                            _blocks.ReplaceWith(m_result, hipos, hipos + 1);
                        }
                        else // binary
                        {
                            m_result = SolveBinary(_blocks, hipos);
                            _blocks.ReplaceWith(m_result, hipos - 1, hipos + 1);
                        }
                    }
                }
                else // priority operator not found
                {
                    ASSERT(false
                           , "Omitted operator found after >" + _blocks[0].Number + '<'
                           , "Parts_Solve: operator not found");
                }
            }

            // End solving with single number
            ASSERT(_blocks.Count == 1, "Nothing to solve", "Parts_Solve: 1-part,1");
            ASSERT(_blocks[0].IsNumber
                   , "Unrecovered >" + _blocks[0].Operator + "< operator"
                   , "Parts_Solve: 1-part,2");
            return;
        }