c# 调用数据库中存储的运算公式 当代码运算出结果

doxob 2018-09-29 03:43:02
比如我有个数据库里面有一列存储的运算公式:canshu1*canshu2+canshu3
所有这3个参数在数据库中已经存储好了。
如何C#把这个运算公式当成代码运算出结果。
当然这些参数和四则运算不是不变的,每次读取的运算公式都可能不同。C#读取数据库不用讲已经完成。就是怎么把读出的公式转化成代码的问题 。请教大神
...全文
1039 29 打赏 收藏 转发到动态 举报
写回复
用AI写文章
29 条回复
切换为时间正序
请发表友善的回复…
发表回复
Lcorel 2018-10-04
  • 打赏
  • 举报
回复
有现成的字符串转数学运算的库
doxob 2018-09-30
  • 打赏
  • 举报
回复
解决了,用了大家推荐的DATATABLE 的computer,动态编译太慢无法忍受。100分均分了谢谢大家。
doxob 2018-09-30
  • 打赏
  • 举报
回复
可能我没有说明白我的意思,
我的意思是从数据库中取出一个字符串是个带有很多变量和运算符的字符串。变量个数不固定,运算方法不固定。但是通过读取的字符串来运算出结果。比如读取的字符串是“a+b*c”,或者是“c/d*e+a”等等,但是变量个数和计算方法不是固定的。读取出来的变量在C#中有对应的变量名,而且也已经通过数据库读取到了数值。最后怎样计算出结果。
yijiu93 2018-09-30
  • 打赏
  • 举报
回复
学习c#语法有没有什么好的入门书啊?
lemter110 2018-09-30
  • 打赏
  • 举报
回复

1
2
3
4
var s = "a+b*c";
var a = 100;
var b= 3.44;
var c = 2330;
木子jim 2018-09-30
  • 打赏
  • 举报
回复
搞成一个sql语句, 然后执行
set @sql=select 你的语句 into sql
excute @sql
kuake56 2018-09-29
  • 打赏
  • 举报
回复
可以试试这个
X-i-n 2018-09-29
  • 打赏
  • 举报
回复
不知道是不是我没理解对题主的题意
        static void Main(string[] args)
        {
            DataTable table = new DataTable();
            table.Columns.Add("a");
            table.Columns.Add("ab");
            table.Columns.Add("c");
            table.Columns.Add("cd");
            table.Columns.Add("e");
            table.Rows.Add(1, 23, 4, 5, "a-ab+c-cd");
            table.Rows.Add(3,2,5,8,"ab+c");
            table.Rows.Add(5, 55, 9, 99, "ab/a*(cd-c)");
            table.Rows.Cast<DataRow>().ToList().ForEach(row => Console.WriteLine(Compute(row, row["e"].ToString())));
            Console.ReadLine();
        }

        static int Compute(DataRow row, string formula)
        {
            foreach(Match field in Regex.Matches(row["e"].ToString(), @"\w+").Cast<Match>().OrderBy(m => -m.Value.Length))
            {
                formula = formula.Replace(field.Value, row[field.Value].ToString());
            }
            return Convert.ToInt32( row.Table.Compute(formula, ""));
        }
lmt5408 2018-09-29
  • 打赏
  • 举报
回复
简单试了下,计算结果没啥问题,就看能不能满足lz的需求了
lmt5408 2018-09-29
  • 打赏
  • 举报
回复
引用 19 楼 lmt5408 的回复:
[quote=引用 16 楼 sp1234 的回复:] 所以我首先搞明白 lz 的需求思路背景,lz 说的“这个运算公式当成代码运算出结果”其实已经划定了他的范围。
private int OperateCount(string opStr)
        {
            Dictionary<string, int> xDic = new Dictionary<string, int>();
            xDic.Add("+", 0);
            xDic.Add("*", 1);

            List<int> numList = new List<int>();
            List<string> OperList = new List<string>();
            for (var i = 0; i < opStr.Length; i++)
            {
                var thisChar = opStr[i].ToString();
                //如果是数字,直接入栈
                if (isNum(thisChar))
                {
                    //如果是数字,直接入栈
                    numList.Add(int.Parse(thisChar));
                }
                else
                {
                    //如果是运算符,则与最后一个运算符比较优先级
                    if (OperList.Count == 0 || xDic[thisChar] > xDic[OperList.Last()])
                    {
                        //如果是第一个运算符或优先级大于上一个运算符则入栈
                        OperList.Add(thisChar);
                    }
                    else if (xDic[thisChar] <= xDic[OperList.Last()])
                    {
                        //这个判断条件只适用于只有加法乘法的简单运算公式
                        Operate(numList, OperList);
                        OperList.Add(thisChar);
                    }
                }
            }

            while (numList.Count > 1)
            {
                Operate(numList, OperList);
            }

            return numList[0];
        }

        private void Operate(List<int> numList, List<string> OperList)
        {
            //ListPop模拟pop操作
            int param1 = ListPop(numList);
            int param2 = ListPop(numList);
            string opChar = ListPop(OperList);
            switch (opChar)
            {
                case "+":
                    numList.Add(param1 + param2);
                    break;
                case "*":
                    numList.Add(param1 * param2);
                    break;
            }
        }
[/quote] 简单实现了下加法和乘法的,原理基本是一样的,就是操作数据栈和操作符栈,更多的运算符优先级二维表lz可以在网上搜索。
lmt5408 2018-09-29
  • 打赏
  • 举报
回复
引用 16 楼 sp1234 的回复:
所以我首先搞明白 lz 的需求思路背景,lz 说的“这个运算公式当成代码运算出结果”其实已经划定了他的范围。
private int OperateCount(string opStr)
        {
            Dictionary<string, int> xDic = new Dictionary<string, int>();
            xDic.Add("+", 0);
            xDic.Add("*", 1);

            List<int> numList = new List<int>();
            List<string> OperList = new List<string>();
            for (var i = 0; i < opStr.Length; i++)
            {
                var thisChar = opStr[i].ToString();
                //如果是数字,直接入栈
                if (isNum(thisChar))
                {
                    //如果是数字,直接入栈
                    numList.Add(int.Parse(thisChar));
                }
                else
                {
                    //如果是运算符,则与最后一个运算符比较优先级
                    if (OperList.Count == 0 || xDic[thisChar] > xDic[OperList.Last()])
                    {
                        //如果是第一个运算符或优先级大于上一个运算符则入栈
                        OperList.Add(thisChar);
                    }
                    else if (xDic[thisChar] <= xDic[OperList.Last()])
                    {
                        //这个判断条件只适用于只有加法乘法的简单运算公式
                        Operate(numList, OperList);
                        OperList.Add(thisChar);
                    }
                }
            }

            while (numList.Count > 1)
            {
                Operate(numList, OperList);
            }

            return numList[0];
        }

        private void Operate(List<int> numList, List<string> OperList)
        {
            //ListPop模拟pop操作
            int param1 = ListPop(numList);
            int param2 = ListPop(numList);
            string opChar = ListPop(OperList);
            switch (opChar)
            {
                case "+":
                    numList.Add(param1 + param2);
                    break;
                case "*":
                    numList.Add(param1 * param2);
                    break;
            }
        }
xuzuning 2018-09-29
  • 打赏
  • 举报
回复
你可以笑话一下这个类
        static void Main(string[] args)
{
var s = "(double a,b,c) => a+b*c";
var a = 100;
var b = 3.44;
var c = 2330;
var r = new ExprParser().Parse(s);
Console.WriteLine(r.Compile().DynamicInvoke(a, b, c)); //8115.2
}
xuzuning 2018-09-29
  • 打赏
  • 举报
回复
    /// <summary>
/// ExprParser has 3 naming scope
/// Global : available for all Parser instance.
/// Parser : available for current Parser instance.
/// Inline : available for current expression.
///
/// User can create multiple parser instance for different naming scope
/// One parser can create multiple expression with the same naming scope
/// One expression can define in-line namespace and parameter only for current expression scope
/// </summary>
public class ExprParser
{
#region namespace, parameter and type: case sensitive

internal static Dictionary<string, Type> SystemType = SetSystemType();
private static Dictionary<string, Type> SetSystemType()
{
// system value types : http://msdn.microsoft.com/en-us/library/s1ax56ch.aspx
Dictionary<string, Type> dic = new Dictionary<string, Type>();
dic.Add("bool", typeof(bool));
dic.Add("char", typeof(char));
dic.Add("string", typeof(string));
dic.Add("byte", typeof(byte));
dic.Add("sbyte", typeof(sbyte));
dic.Add("short", typeof(short));
dic.Add("ushort", typeof(ushort));
dic.Add("int", typeof(int));
dic.Add("uint", typeof(uint));
dic.Add("long", typeof(long));
dic.Add("ulong", typeof(ulong));
dic.Add("float", typeof(float));
dic.Add("double", typeof(double));
dic.Add("decimal", typeof(decimal));
dic.Add("enum", typeof(Enum));
dic.Add("object", typeof(object));
return dic;
}
internal static Dictionary<Type, Type> NullableType = SetNullableType();
private static Dictionary<Type, Type> SetNullableType()
{
Dictionary<Type, Type> dic = new Dictionary<Type, Type>();
dic.Add(typeof(bool), typeof(bool?));
dic.Add(typeof(char), typeof(char?));
dic.Add(typeof(byte), typeof(byte?));
dic.Add(typeof(sbyte), typeof(sbyte?));
dic.Add(typeof(short), typeof(short?));
dic.Add(typeof(ushort), typeof(ushort?));
dic.Add(typeof(int), typeof(int?));
dic.Add(typeof(uint), typeof(uint?));
dic.Add(typeof(long), typeof(long?));
dic.Add(typeof(ulong), typeof(ulong?));
dic.Add(typeof(float), typeof(float?));
dic.Add(typeof(double), typeof(double?));
dic.Add(typeof(decimal), typeof(decimal?));
return dic;
}


// namespace for static data type
public static Using Using = new Using();
internal Assembly caller_assembly = null;

// parameter type
public static Dictionary<string, Type> GlobalParameterType = new Dictionary<string, Type>(); // Global scope
public Dictionary<string, Type> ParameterType = new Dictionary<string, Type>(); // Parser scope
private Dictionary<string, Type> inlineParameterType = null; // Expr scope
// parameter value
public static Dictionary<string, object> GlobalParameterValue = new Dictionary<string, object>(); // Global scope
public Dictionary<string, object> ParameterValue = new Dictionary<string, object>(); // Parser scope


/// <summary>
/// check by order:
/// - System Type // user type cannot be the same with system type. check system type first is for performance
/// - Type.GetType(type_name)
/// - Type from Local Namespace
/// - Type from Globel Namespace
/// limitation:
/// Type.GetType use AssmblyQulifiedName: "ns.type, ns". not include version info, "type" part not include "."
/// </summary>
/// <param name="name">type or instance object name</param>
/// <returns></returns>
internal Type QueryStaticType(string type_name)
{
// check with dicSystemType
if (SystemType.ContainsKey(type_name))
return SystemType[type_name];

// check type_name itself
Type t = null;
if ((t = Type.GetType(type_name)) != null) return t; // check System(mscorlib) assembly
if (caller_assembly != null && (t = caller_assembly.GetType(type_name)) != null) return t; // check caller assembly

foreach (string ns in Using.namespace_list.Keys)
{
string full_type_name = ns + "." + type_name;
if (Using.namespace_list[ns] == null)
{
if ((t = Type.GetType(full_type_name)) != null) return t; // check System(mscorlib) assembly
if (caller_assembly != null && (t = caller_assembly.GetType(full_type_name)) != null) return t; // check caller assembly
if ((t = Type.GetType(full_type_name + ", " + ns)) != null) return t; // check namespace as assembly name
}
else if (Using.namespace_list[ns] != null && (t = Using.namespace_list[ns].GetType(full_type_name)) != null) return t;
}
if (type_name.Contains(".") && (t = Type.GetType(type_name + ", " + type_name.Substring(0, type_name.LastIndexOf('.')))) != null)
return t;

//// check with Namespace
//if (this.Namespace != null)
//{
// foreach (string ns in this.Namespace)
// if ((t = Type.GetType(ns + "." + type_name)) != null
// || (t = Type.GetType(ns + "." + type_name + ", " + ns)) != null) return t;
//}
//// check with GlobalNamespace
//if (GlobalNamespace != null)
//{
// foreach (string ns in GlobalNamespace)
// if ((t = Type.GetType(ns + "." + type_name)) != null
// || (t = Type.GetType(ns + "." + type_name + ", " + ns)) != null) return t;
//}
//// check with localNamespace
//if (inlineNamespace != null)
//{
// foreach (string ns in inlineNamespace)
// if ((t = Type.GetType(ns + "." + type_name)) != null
// || (t = Type.GetType(ns + "." + type_name + ", " + ns)) != null) return t;
//}
return null;
}

/// <summary>
/// check by order
/// Parameter Type
/// Globel Parameter Type
/// queryParameterValue(parameter_name)
/// </summary>
/// <param name="parameter_name"></param>
/// <returns></returns>
internal Type QueryParameterType(string parameter_name)
{
if (ParameterType != null && ParameterType.ContainsKey(parameter_name))
return ParameterType[parameter_name];
else if (GlobalParameterType.ContainsKey(parameter_name))
return GlobalParameterType[parameter_name];
else if (inlineParameterType != null && inlineParameterType.ContainsKey(parameter_name))
return inlineParameterType[parameter_name];
return null;
}


// implicit conversion
internal static Dictionary<Type, List<Type>> dicImplicitConversion = SetImplicitConversionMap();
internal static Dictionary<Type, List<Type>> SetImplicitConversionMap()
{
Dictionary<Type, List<Type>> dic = new Dictionary<Type, List<Type>>();
dic.Add(typeof(char), new List<Type>(new Type[] { typeof(char), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal), typeof(char?), typeof(ushort?), typeof(int?), typeof(uint?), typeof(long?), typeof(ulong?), typeof(float?), typeof(double?), typeof(decimal?) }));
dic.Add(typeof(byte), new List<Type>(new Type[] { typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal), typeof(byte?), typeof(short?), typeof(ushort?), typeof(int?), typeof(uint?), typeof(long?), typeof(ulong?), typeof(float?), typeof(double?), typeof(decimal?) }));
dic.Add(typeof(sbyte), new List<Type>(new Type[] { typeof(sbyte), typeof(short), typeof(int), typeof(long), typeof(float), typeof(double), typeof(decimal), typeof(sbyte?), typeof(short?), typeof(int?), typeof(long?), typeof(float?), typeof(double?), typeof(decimal?) }));
dic.Add(typeof(short), new List<Type>(new Type[] { typeof(short), typeof(int), typeof(long), typeof(float), typeof(double), typeof(decimal), typeof(short?), typeof(int?), typeof(long?), typeof(float?), typeof(double?), typeof(decimal?) }));
dic.Add(typeof(ushort), new List<Type>(new Type[] { typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal), typeof(ushort?), typeof(int?), typeof(uint?), typeof(long?), typeof(ulong?), typeof(float?), typeof(double?), typeof(decimal?) }));
dic.Add(typeof(int), new List<Type>(new Type[] { typeof(int), typeof(long), typeof(float), typeof(double), typeof(decimal), typeof(int?), typeof(long?), typeof(float?), typeof(double?), typeof(decimal?) }));
dic.Add(typeof(uint), new List<Type>(new Type[] { typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal), typeof(uint?), typeof(long?), typeof(ulong?), typeof(float?), typeof(double?), typeof(decimal?) }));
dic.Add(typeof(long), new List<Type>(new Type[] { typeof(long), typeof(float), typeof(double), typeof(decimal), typeof(long?), typeof(float?), typeof(double?), typeof(decimal?) }));
dic.Add(typeof(ulong), new List<Type>(new Type[] { typeof(ulong), typeof(float), typeof(
  • 打赏
  • 举报
回复
所以我首先搞明白 lz 的需求思路背景,lz 说的“这个运算公式当成代码运算出结果”其实已经划定了他的范围。
lmt5408 2018-09-29
  • 打赏
  • 举报
回复
引用 13 楼 sp1234 的回复:
[quote=引用 11 楼 lmt5408 的回复:] 哪用那么麻烦,大学的时候我记得算法课应该有学过的啊。就算按顺序读取字符串,生成两个栈,一个数据栈,一个算符栈,然后根据算符优先级取值运算,最后得到一个数,就是计算结果。
lz 要的是任意调用当前 c# 程序中的各种变量,能够得出计算结果。[/quote] 原理是一样的。如果各种变量包括非数字的数据,那就把 加法 乘法 等各种运算根据自己需要实现下就好。
lmt5408 2018-09-29
  • 打赏
  • 举报
回复
@doxob https://www.cnblogs.com/zabery/archive/2010/08/11/1797602.html
  • 打赏
  • 举报
回复
比如说,你要运算个
1+2*3
这不算什么,那么运算一下
if(x1 > 1000)
{
    return Math.Power(x2, 2) + x3;
}
else if(d1 > new Date(2018,9,29) && Math.abs(p1)>0.0001)
{
    return x2+x3/p1;
}
试试看你怎么生成两个栈来计算呢?这显然就比两个栈需要更多。
lmt5408 2018-09-29
  • 打赏
  • 举报
回复
哪用那么麻烦,大学的时候我记得算法课应该有学过的啊。就算按顺序读取字符串,生成两个栈,一个数据栈,一个算符栈,然后根据算符优先级取值运算,最后得到一个数,就是计算结果。
  • 打赏
  • 举报
回复
引用 11 楼 lmt5408 的回复:
哪用那么麻烦,大学的时候我记得算法课应该有学过的啊。就算按顺序读取字符串,生成两个栈,一个数据栈,一个算符栈,然后根据算符优先级取值运算,最后得到一个数,就是计算结果。
lz 要的是任意调用当前 c# 程序中的各种变量,能够得出计算结果。
X-i-n 2018-09-29
  • 打赏
  • 举报
回复
我教你一个办法,不用十年,十分钟就够了。 既然已经连接了数据库,用值把参数名替换以后,直接用SQL语句拼出来是最便捷的。 SELECT 3*5+8 或者用DataTable的Compute方法计算 不过题主动手能力略微捉鸡啊,刚才顺手搜了一下,"C# 公式运算",一屏结果都是答案,一个不相干的搜索结果都没有。
加载更多回复(9)

110,571

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧