//and
        private static CalNum and(List<CalNum> numList)
        {
            CalNum result = null;

            if (numList.Count == 2)
            {
                if (numList[0].DoubleValue.ToString().IndexOf("E") == -1
                    && numList[0].DoubleValue.ToString().IndexOf("E") == -1
                    && (numList[0].DoubleValue.ToString().IndexOf(".") != -1
                    || numList[1].DoubleValue.ToString().IndexOf(".") != -1))
                {
                    throw (new Exception("不支持小数"));
                }
                else
                {
                    result = new CalNum((long)numList[0].DoubleValue & (long)numList[1].DoubleValue);
                }
            }
            else
            {
                MakeException("参数个数不正确");
            }

            return result;
        }
        /// <summary>
        /// 求平均数
        /// </summary>
        private static CalNum average(List<CalNum> numList)
        {
            CalNum result = null;

            double sum = 0;
            if (numList.Count != 0)
            {
                for (int i = 0; i < numList.Count; i++)
                {
                    sum += numList[i].DoubleValue;
                }
                result = new CalNum(sum / numList.Count);
            }

            return result;
        }
        /// <summary>
        /// sinh
        /// </summary>
        private static CalNum Cal_Sinh(List<CalNum> numList)
        {
            CalNum result = null;

            if (numList.Count == 1)
            {
                result = new CalNum(Math.Sinh(numList[0].DoubleValue));
            }
            else
            {
                MakeException("参数个数不正确");
            }

            return result;
        }
        /// <summary>
        /// 获取数字
        /// </summary>
        private CalNum GetNum(ref string str)
        {
            CalNum result = null;

            result = new CalNum(str);

            //更新str
            str = "";

            return result;
        }
        /// <summary>
        /// 组合
        /// </summary>
        private static CalNum Cal_nCr(List<CalNum> numList)
        {
            CalNum result = null;

            if (numList.Count == 2)
            {
                result = new CalNum(Common.Fac((int)numList[0].DoubleValue)
                    / (Common.Fac((int)numList[0].DoubleValue - (int)numList[1].DoubleValue)
                    * Common.Fac((int)numList[1].DoubleValue)));
            }
            else
            {
                MakeException("参数个数不正确");
            }

            return result;
        }
        /// <summary>
        /// 加
        /// </summary>
        private static CalNum Cal_Plus(List<CalNum> numList)
        {
            CalNum result = null;

            if (numList.Count == 1)
            {
                result = new CalNum(numList[0].DoubleValue);
            }
            else if (numList.Count == 2)
            {
                //转换成整数再运算,结果再转换成小数
                int decimalLength = GetDecimalLength(numList[0].DoubleValue, numList[1].DoubleValue);
                result = new CalNum((numList[0].DoubleValue * Math.Pow(10, decimalLength) + numList[1].DoubleValue * Math.Pow(10, decimalLength))
                    / Math.Pow(10, decimalLength));
            }
            else
            {
                MakeException("参数个数不正确");
            }

            return result;
        }
        //Lsh
        private static CalNum Lsh(List<CalNum> numList)
        {
            CalNum result = null;

            if (numList.Count == 2)
            {
                if (numList[0].DoubleValue.ToString().IndexOf("E") == -1
                    && numList[0].DoubleValue.ToString().IndexOf("E") == -1
                    && (numList[0].DoubleValue.ToString().IndexOf(".") != -1
                    || numList[1].DoubleValue.ToString().IndexOf(".") != -1))
                {
                    throw (new Exception("不支持小数"));
                }
                else
                {
                    int length1 = Convert.ToString((long)numList[0].DoubleValue, 2).Length;
                    int length2 = (int)numList[1].DoubleValue;
                    if (length1 + length2 > 63)
                    {
                        MakeException("溢出");
                    }
                    result = new CalNum((long)numList[0].DoubleValue << (int)numList[1].DoubleValue);
                }
            }
            else
            {
                MakeException("参数个数不正确");
            }

            return result;
        }
        /// <summary>
        /// log
        /// </summary>
        private static CalNum Cal_Log(List<CalNum> numList)
        {
            CalNum result = null;

            if (numList.Count == 1)
            {
                result = new CalNum(Math.Log10(numList[0].DoubleValue));
            }
            //两个参数的情况
            else if (numList.Count == 2)
            {
                result = new CalNum(Math.Log(numList[0].DoubleValue, numList[1].DoubleValue));
            }
            else
            {
                MakeException("参数个数不正确");
            }

            return result;
        }
        /// <summary>
        /// 度分秒与小数形式相互转换
        /// </summary>
        private static CalNum dms(List<CalNum> numList)
        {
            CalNum result = null;

            double d = 0;
            double f = 0;
            double m = 0;
            if (numList.Count == 1)
            {
                d = Math.Floor(numList[0].DoubleValue);
                f = (numList[0].DoubleValue - d) * 60;
                m = (f - Math.Floor(f)) * 60;

                result = new CalNum(d.ToString() + "| 度 |"
                    + Math.Floor(f).ToString() + "| 分 |"
                    + m.ToString() + "| 秒");
            }
            else if (numList.Count == 2)
            {
                result = new CalNum(numList[0].DoubleValue + numList[1].DoubleValue / 60);
            }
            else if (numList.Count == 3)
            {
                result = new CalNum(numList[0].DoubleValue + numList[1].DoubleValue / 60 + numList[2].DoubleValue / 3600);
            }
            else
            {
                MakeException("参数个数不正确");
            }

            return result;
        }
        /// <summary>
        /// 获取变量值或用户自定义函数的计算结果
        /// </summary>
        /// <param name="tag">变量标识符</param>
        private static CalNum GetVariableOrCustomFunResultValue(string tag, List<CalNum> numList)
        {
            CalNum result = null;

            if (numList.Count == 0)//变量
            {
                string[] variables = Properties.Settings.Default.strVariables.Split('|');

                //扫描变量键值列表
                for (int i = 0; i < variables.Length; i++)
                {
                    //找到变量
                    if (variables[i] == tag)
                    {
                        double d;
                        if (double.TryParse(variables[i + 1], out d))
                        {
                            result = new CalNum(d);
                        }
                        else
                        {
                            result = new CalNum(variables[i + 1]);
                        }
                    }
                }
            }
            else//用户自定义函数
            {
                try
                {
                    StringCollection funList = Properties.Settings.Default.funList;
                    if (funList != null)
                    {
                        //逐个扫描存在的函数,查找函数
                        for (int i = 0; i < funList.Count; i++)
                        {
                            if (funList[i].Split('|')[0] == tag)//找到函数
                            {
                                //参数个数不正确
                                if (numList.Count != funList[i].Split('|')[3].Split(',').Length)
                                {
                                    throw new Exception("|参数个数不正确");
                                }

                                string[] funParts = funList[i].Split('|');//分隔
                                StringBuilder funExpr = new StringBuilder(funParts[2]);//取出表达式

                                //替换表达式中的变量
                                for (int k = 0; k < numList.Count; k++)
                                {
                                    bool bl;
                                    //替换,用参数的stringValue替换且两边加上括号
                                    funExpr.Replace(Common.DeleteAnnotate(funParts[3].Split(',')[k], out bl), "(" + numList[k].stringValue + ")");
                                }

                                //分段函数
                                if (funExpr.ToString().IndexOf("subfuns") != -1)
                                {
                                    return subfuns(funExpr, numList);//不再进行后面的计算,返回
                                }

                                //计算
                                bool bl1;
                                string str = Common.DeleteAnnotate(funExpr.ToString(), out bl1);//删除注释
                                CalValList valList = new CalValList(str);
                                CalResult calResult = valList.Calculate();
                                if (calResult.numList.Count == 1)//一个计算结果
                                {
                                    result = calResult.numList[0];
                                }
                                else//多个计算结果
                                {
                                    result = new CalNum(calResult.GeneralResultToShow.Trim());
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message + "|(函数'" + tag + "'的表达式是'" + Common.GetFunExpr(tag) + "')");
                }
            }

            return result;
        }
        /// <summary>
        /// 换算函数
        /// </summary>
        /// <param name="coefficient">换算系数</param>
        private static CalNum Conversion(double coefficient, List<CalNum> numList)
        {
            CalNum result = null;

            double doubleResult = numList[2].DoubleValue * coefficient;
            string strResult = numList[2].DoubleValue.ToString()
                + "|" + numList[0].stringValue
                + " = |"
                + doubleResult.ToString()
                + "|" + numList[1].stringValue;
            result = new CalNum(doubleResult, strResult);

            return result;
        }
        /// <summary>
        /// 十进制转换成八进制
        /// </summary>
        private static CalNum Cal_ToO(List<CalNum> numList)
        {
            CalNum result = null;

            if (numList.Count == 1)
            {
                if (numList[0].DoubleValue.ToString().IndexOf("E") == -1
                    && numList[0].DoubleValue.ToString().IndexOf(".") != -1)
                {
                    throw (new Exception("不支持小数"));
                }
                result = new CalNum(Convert.ToString((long)numList[0].DoubleValue, 8));
            }
            else
            {
                MakeException("参数个数不正确");
            }

            return result;
        }
        /// <summary>
        /// 替换运算因子
        /// </summary>
        /// <param name="num">用于替换的操作数</param>
        /// <param name="count">要替换的运算因子的个数</param>
        /// <param name="pos">替换位置</param>
        private void ReplaceVal(CalNum num, int count, int pos)
        {
            valList[pos] = new CalVal(num);
            valList.RemoveRange(pos + 1, count - 1);

            //左右括号同时存在,处理左右括号
            if (pos >= 1
                && valList[pos - 1].OpeType == OpeType.leftParenthesis
                && pos + 1 < valList.Count
                && valList[pos + 1].OpeType == OpeType.rightParenthesis)
            {
                //如sin(9-7),average(9-7)
                if (!(pos >= 2
                    && valList[pos - 2].OpeType == OpeType.right))
                {
                    //删除左右括号
                    valList[pos - 1] = valList[pos];
                    valList.RemoveRange(pos, 2);
                }
            }
        }
        /// <summary>
        /// 弧度转换成角度
        /// </summary>
        private static CalNum Cal_Degree(List<CalNum> numList)
        {
            CalNum result = null;

            if (numList.Count == 1)
            {
                result = new CalNum(numList[0].DoubleValue * 180 / Math.PI);
            }
            else
            {
                MakeException("参数个数不正确");
            }

            return result;
        }
        /// <summary>
        /// 产生随机数
        /// </summary>
        private static CalNum Rnd(List<CalNum> numList)
        {
            CalNum result = null;

            if (numList.Count == 2)
            {
                Random rnd = new Random();
                result = new CalNum(rnd.Next((int)numList[0].DoubleValue, (int)(numList[1].DoubleValue + 1)));
            }
            else
            {
                MakeException("参数个数不正确");
            }

            return result;
        }
        /// <summary>
        /// !(阶乘)
        /// </summary>
        private static CalNum Cal_Fac(List<CalNum> numList)
        {
            CalNum result = null;

            if (numList.Count == 1)
            {
                int n;

                try
                {
                    n = int.Parse(numList[0].DoubleValue.ToString());
                }
                catch
                {
                    throw (new Exception("阶乘的操作数必须是整数"));
                }

                result = new CalNum(Common.Fac(n));
            }
            else
            {
                MakeException("参数个数不正确");
            }

            return result;
        }
        //Rsh
        private static CalNum Rsh(List<CalNum> numList)
        {
            CalNum result = null;

            if (numList.Count == 2)
            {
                if (numList[0].DoubleValue.ToString().IndexOf("E") == -1
                    && numList[0].DoubleValue.ToString().IndexOf("E") == -1
                    && (numList[0].DoubleValue.ToString().IndexOf(".") != -1
                    || numList[1].DoubleValue.ToString().IndexOf(".") != -1))
                {
                    throw (new Exception("不支持小数"));
                }
                else
                {
                    int length1 = Convert.ToString((long)numList[0].DoubleValue, 2).Length;
                    int length2 = (int)numList[1].DoubleValue;
                    string str = null;
                    if (length2 > 63)
                    {
                        MakeException("溢出");
                    }
                    if (length2 <= length1)
                    {
                        str = Convert.ToString((long)numList[0].DoubleValue, 2).Substring(length1 - length2, length2);
                    }
                    else
                    {
                        str = Convert.ToString((long)numList[0].DoubleValue, 2);
                        for (int i = 0; i < length2 - length1; i++)
                        {
                            str = str.Insert(0, "0");
                        }
                    }
                    double d = 0;
                    for (int i = 0; i < str.Length; i++)
                    {
                        if (str[i] != '0')
                        {
                            d += 1 / Math.Pow(2, (i + 1));
                        }
                    }
                    result = new CalNum(((long)numList[0].DoubleValue >> (int)numList[1].DoubleValue) + d);
                }
            }
            else
            {
                MakeException("参数个数不正确");
            }

            return result;
        }
        /// <summary>
        /// 乘
        /// </summary>
        private static CalNum Cal_Multiply(List<CalNum> numList)
        {
            CalNum result = null;

            if (numList.Count == 2)
            {
                result = new CalNum(numList[0].DoubleValue * numList[1].DoubleValue);
            }
            else
            {
                MakeException("参数个数不正确");
            }

            return result;
        }
        /// <summary>
        /// 分段函数
        /// </summary>
        private static CalNum subfuns(StringBuilder funExpr, List<CalNum> numList)
        {
            CalNum result = null;

            if (funExpr.ToString().IndexOf("subfuns(") == -1)
            {
                MakeException("分段函数语法不正确");
            }
            if (funExpr[funExpr.Length - 1] != ')')
            {
                MakeException("分段函数语法不正确");
            }
            funExpr.Replace("subfuns(", "");
            funExpr.Remove(funExpr.Length - 1, 1);
            CalNum num = numList[0];//仅支持对第一个参数分段

            bool isBeyond = true;//是否越界
            string[] funs = funExpr.ToString().Split(',');

            if (funs.Length % 3 != 0)
            {
                MakeException("subfuns的参数个数不正确,必须三个为一组");
            }

            for (int i = 0; i < funs.Length; i += 3)//每三个一组:左边界、右边界、对应表达式
            {
                double leftBoundary = double.MinValue;//左边界
                double rightBoundary = double.MaxValue;//右边界
                bool leftHollow = false;//左边界是否空心,默认是实心
                bool rightHollow = false;//右边界是否空心,默认是实心
                bool isIn = false;//参数是否在该范围内,默认false

                if (funs[i].IndexOf(">") != -1)//左边界空心
                {
                    leftHollow = true;
                    leftBoundary = double.Parse(funs[i].Substring(1));
                }
                else
                {
                    leftBoundary = double.Parse(funs[i]);
                }
                if (funs[i + 1].IndexOf("<") != -1)//右边界空心
                {
                    rightHollow = true;
                    rightBoundary = double.Parse(funs[i + 1].Substring(1));
                }
                else
                {
                    rightBoundary = double.Parse(funs[i + 1]);
                }

                #region 判断参数是否在当前范围内
                if (leftHollow == true)//左边界空心
                {
                    if (rightHollow == true)//右边界空心
                    {
                        if (num.DoubleValue > leftBoundary
                            && num.DoubleValue < rightBoundary)
                        {
                            isIn = true;
                        }
                    }
                    else//右边界实心
                    {
                        if (num.DoubleValue > leftBoundary
                            && num.DoubleValue <= rightBoundary)
                        {
                            isIn = true;
                        }
                    }
                }
                else//左边界实心
                {
                    if (rightHollow == true)//右边界空心
                    {
                        if (num.DoubleValue >= leftBoundary
                            && num.DoubleValue < rightBoundary)
                        {
                            isIn = true;
                        }
                    }
                    else//右边界实心
                    {
                        if (num.DoubleValue >= leftBoundary
                            && num.DoubleValue <= rightBoundary)
                        {
                            isIn = true;
                        }
                    }
                }
                #endregion

                if (isIn)//如果参数在当前范围内
                {
                    isBeyond = false;//没有越界
                    //计算
                    bool bl1;
                    string str = Common.DeleteAnnotate(funs[i + 2], out bl1);//删除注释
                    CalValList valList = new CalValList(str);
                    CalResult calResult = valList.Calculate();
                    if (calResult.numList.Count == 1)//一个计算结果
                    {
                        result = calResult.numList[0];
                    }
                    else//多个计算结果
                    {
                        result = new CalNum(calResult.GeneralResultToShow.Trim());
                    }
                    //跳出循环
                    break;
                }
            }
            if (isBeyond)
            {
                MakeException("输入的参数超出定义的范围");
            }

            return result;
        }
        /// <summary>
        /// 八进制转换成十进制
        /// </summary>
        private static CalNum Cal_O(List<CalNum> numList)
        {
            CalNum result = null;

            if (numList.Count == 1)
            {
                result = new CalNum(Convert.ToDouble(Convert.ToInt64(numList[0].stringValue, 8)));
            }
            else
            {
                MakeException("参数个数不正确");
            }

            return result;
        }
        /// <summary>
        /// 样本标准方差
        /// </summary>
        private static CalNum SwatchStandardVariance(List<CalNum> numList)
        {
            CalNum result = null;

            //特殊情况
            if (numList.Count == 1)
            {
                return new CalNum(0);
            }

            double s = 0;
            double avg = average(numList).DoubleValue;
            for (int i = 0; i < numList.Count; i++)
            {
                s += Math.Pow(numList[i].DoubleValue - avg, 2);
            }
            s /= (numList.Count - 1);
            s = Math.Sqrt(s);

            result = new CalNum(s);

            return result;
        }
        /// <summary>
        /// 乘方
        /// </summary>
        private static CalNum Cal_Pow(List<CalNum> numList)
        {
            CalNum result = null;

            if (numList.Count == 2)
            {
                result = new CalNum(Math.Pow(numList[0].DoubleValue, numList[1].DoubleValue));
            }
            else
            {
                MakeException("参数个数不正确");
            }

            if (double.IsInfinity(result.DoubleValue))
            {
                MessageBox.Show("指数运算'^'的运算结果为无穷大,可能会导致'log'等对数运算出现错误", "警告");
            }

            return result;
        }
        /// <summary>
        /// 计算
        /// </summary>
        /// <param name="ope">运算符</param>
        /// <param name="numList">参数列表</param>
        public static CalNum Calculate(CalOpe ope, List<CalNum> numList)
        {
            CalNum result = null;

            try
            {
                switch (ope.tag)
                {
                    //下面是运算符
                    case "+":
                        result = Cal_Plus(numList);
                        break;
                    case "-":
                        result = Cal_Minus(numList);
                        break;

                    case "*":
                        result = Cal_Multiply(numList);
                        break;
                    case "/":
                        result = Cal_Divide(numList);
                        break;
                    case "Mod":
                    case "mod":
                        result = Cal_Mod(numList);
                        break;

                    case "^":
                        result = Cal_Pow(numList);
                        break;

                    case "Exp":
                    case "exp":
                        result = Cal_Exp(numList);
                        break;
                    case "ln":
                        result = Cal_Ln(numList);
                        break;
                    case "log":
                        result = Cal_Log(numList);
                        break;
                    case "sqrt":
                        result = Cal_Sqrt(numList);
                        break;

                    case "sin":
                        result = Cal_Sin(numList);
                        break;
                    case "cos":
                        result = Cal_Cos(numList);
                        break;
                    case "tan":
                        result = Cal_Tan(numList);
                        break;
                    case "asin":
                        result = Cal_Asin(numList);
                        break;
                    case "acos":
                        result = Cal_Acos(numList);
                        break;
                    case "atan":
                        result = Cal_Atan(numList);
                        break;
                    case "sinh":
                        result = Cal_Sinh(numList);
                        break;
                    case "cosh":
                        result = Cal_Cosh(numList);
                        break;
                    case "tanh":
                        result = Cal_Tanh(numList);
                        break;

                    case "nCr": //组合
                    case "ncr":
                        result = Cal_nCr(numList);
                        break;
                    case "nAr": //排列
                    case "nar":
                        result = Cal_nAr(numList);
                        break;

                    case "!":
                        result = Cal_Fac(numList);
                        break;
                    case "%":
                        result = Cal_Per(numList);
                        break;
                    case "度":
                        result = Cal_Du(numList);
                        break;
                    case "toDegree":
                        result = Cal_Degree(numList);
                        break;

                    case "BIN": //二进制
                        result = Cal_B(numList);
                        break;
                    case "OCT": //八进制
                        result = Cal_O(numList);
                        break;
                    case "HEX": //十六进制
                        result = Cal_H(numList);
                        break;
                    case "toB": //二进制
                        result = Cal_ToB(numList);
                        break;
                    case "toO": //八进制
                        result = Cal_ToO(numList);
                        break;
                    case "toH": //十六进制
                        result = Cal_ToH(numList);
                        break;

                    //下面是常数
                    case "PI":
                    case "pi":
                        result = new CalNum(Math.PI);
                        break;
                    case "e":
                        result = new CalNum(Math.E);
                        break;
                    case "rnd":
                        Random rnd = new Random();
                        result = new CalNum(rnd.NextDouble());
                        break;

                    //下面是函数
                    case "avg":
                        result = average(numList);
                        break;
                    case "sum":
                        result = sum(numList);
                        break;
                    case "conv":
                        result = UnitConversion(numList);
                        break;
                    case "s":
                        result = SwatchStandardVariance(numList);
                        break;
                    case "dms":
                        result = dms(numList);
                        break;

                    //下面是逻辑运算
                    case "and":
                    case "And":
                        result = and(numList);
                        break;
                    case "or":
                    case "Or":
                        result = or(numList);
                        break;
                    case "xor":
                    case "Xor":
                        result = xor(numList);
                        break;
                    case "not":
                    case "Not":
                        result = not(numList);
                        break;

                    //下面是位移运算符
                    case ">>":
                    case "Rsh":
                        result = Rsh(numList);
                        break;
                    case "<<":
                    case "Lsh":
                        result = Lsh(numList);
                        break;

                    //其他运算符
                    case "sgn":
                    case "Sgn":
                    case "Sign":
                    case "sign":
                        result = sgn(numList);
                        break;
                    case "int":
                    case "Int":
                        result = Int(numList);
                        break;
                    case "Abs":
                    case "abs":
                        result = abs(numList);
                        break;
                    case "Rnd":
                        result = Rnd(numList);
                        break;

                    //分段函数
                    case "subfuns":
                        MakeException("该函数不能这样使用");
                        break;

                    //变量或用户自定义函数
                    default:
                        result = GetVariableOrCustomFunResultValue(ope.tag, numList);
                        break;

                }
            }
            catch (Exception ex)
            {
                throw (new Exception("在'" + ope.tag + "'附近可能存在错误:" + ex.Message));
            }

            if (result == null)
            {
                throw (new Exception("在'" + ope.tag + "'附近可能存在错误"));
            }

            if (result.stringValue == "非数字")
            {
                throw (new Exception("'" + ope.tag + "'运算的计算结果非数字"));
            }

            return result;
        }
Example #24
0
 /// <summary>
 /// 构造函数
 /// </summary>
 public CalVal(CalNum num)
 {
     this.num = num;
     this.type = ValType.Number;
 }
        /// <summary>
        /// 获取数字
        /// </summary>
        private CalNum GetNum(ref string str, int opePos)
        {
            CalNum result = null;

            result = new CalNum(str.Substring(0, opePos));

            //更新str
            str = str.Substring(opePos);

            return result;
        }