首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >动态表达式中的代码嗅觉

动态表达式中的代码嗅觉
EN

Stack Overflow用户
提问于 2011-01-13 10:32:17
回答 3查看 335关注 0票数 0

这段代码解决了http://www.programgood.net/2011/01/13/DynamicOperatorsGuernseyChallenge.aspx中描述的一个有趣的难题。

问题:,这里似乎有很多重复。干巴巴的(不要重复自己)原则在这里闪现出来。有人看到重构了吗?

代码语言:javascript
复制
        string opZ = "";
        string opA = "";
        string opB = "";
        string opC = "";
        string opD = "";
        for (int h = 1; h <= 2; h++) // making the first number positive or negative
        {
            if (h == 1) opZ = "";
            if (h == 2) opZ = "-";

            for (int i = 1; i <= 4; i++)
            {
                if (i == 1) opA = "*";
                if (i == 2) opA = "/";
                if (i == 3) opA = "+";
                if (i == 4) opA = "-";
                for (int j = 1; j <= 4; j++)
                {
                    if (j == 1) opB = "*";
                    if (j == 2) opB = "/";
                    if (j == 3) opB = "+";
                    if (j == 4) opB = "-";
                    for (int k = 1; k <= 4; k++)
                    {
                        if (k == 1) opC = "*";
                        if (k == 2) opC = "/";
                        if (k == 3) opC = "+";
                        if (k == 4) opC = "-";
                        for (int l = 1; l <= 4; l++)
                        {
                            if (l == 1) opD = "*";
                            if (l == 2) opD = "/";
                            if (l == 3) opD = "+";
                            if (l == 4) opD = "-";
                            string expression = opZ + 1 + opA + 3 + opB + 5 + opC + 7 + opD + 9;
                            DataTable dummy = new DataTable();
                            double result = Convert.ToDouble(dummy.Compute(expression, string.Empty));
                            if (result == 3)
                                Debug.WriteLine(expression + " = 3");

                            if (result == 47)
                                Debug.WriteLine(expression + " = 47");

                            if (result == 18)
                                Debug.WriteLine(expression + " = 18");

                        }
                    }
                }
            }
        }
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-01-13 10:35:49

好吧,第一个明显的重构就是有一个操作符数组:

代码语言:javascript
复制
String[] operators = { null, "*", "/", "+", "-" };

然后使用:

代码语言:javascript
复制
opC = operators[j]; // etc

(就我个人而言,我会使用从0到3的循环,而不是从1到4-这是更惯用的IMO,但这是另一回事。)

还有建立排列的方法。实际上,我会使用LINQ实现这个目标:

代码语言:javascript
复制
string[] prefixes = { "", "-" };
string[] operators = { "*", "/", "+", "-" };
var expressions = from prefix in prefixes
                  from opA in operators
                  from opB in operators
                  from opC in operators
                  from opD in operators
                  select prefix + 1 + opA + 3 + opB + 5 + opC + 7 + opD + 9;

foreach (string expression in expressions)
{
    ...
}
票数 3
EN

Stack Overflow用户

发布于 2011-01-13 10:40:08

代码语言:javascript
复制
char[] ops = new [] {'*','/','+','-'};
foreach(string opA in ops)
 foreach(string opB in ops)
  foreach(string opC in ops)
   foreach(string opD in ops)
    foreach(string opZ in new []{'-',' '}) {
     string expression = opZ + 1 + opA + 3 + opB + 5 + opC + 7 + opD + 9;
     DataTable dummy = new DataTable();
     double result = Convert.ToDouble(dummy.Compute(expression, string.Empty));
     if (result == 3)
       Debug.WriteLine(expression + " = 3");
     if (result == 47)
       Debug.WriteLine(expression + " = 47");
     if (result == 18)
      Debug.WriteLine(expression + " = 18");
    } 
票数 1
EN

Stack Overflow用户

发布于 2011-01-13 12:08:07

我认为在使用DataTable.Compute时这样做是没有意义的,但是

代码语言:javascript
复制
var calculator = new DataTable () ;
var operators  = "*/+-" ;
for (int i = 0 ; i < 0x200 ; ++i)
{
  var value = calculator.Compute (String.Format ("{0}1{1}3{2}5{3}7{4}9",
    (i & 0x100) != 0 ? "-" : "",
    operators[(i >> 0) & 3],
    operators[(i >> 2) & 3],
    operators[(i >> 4) & 3],
    operators[(i >> 6) & 3]), String.Empty) ;
  ...
}

否则,如果有点深奥的话,这肯定会更快:

代码语言:javascript
复制
var opstrings = "+-*/" ;
var operators = new Func<int, int, int>[] {
  (a, b) => a + b,
  (a, b) => a - b,
  (a, b) => a * b,
  (a, b) => a / b, } ;
for (int i = 0 ; i < 0x200 ; ++i)
{
  var stack = 0 ; // seed value
  var last  = 0 ; // imitate + for lowest precedence
  var value =(i & 0x100) != 0 ? -1 : 1 ;

  for (int j = 0 ; j < 5 ; ++j)    // extra item to force last reduction
  {
    var oper  = (i >> j * 2) & 3 ; // "input" operator
    var input =  3  + j * 2 ;      // "input" number
    if (oper / 2 <= last / 2)      // reduce below top?
    {
      stack = operators[last] (stack, value) ;
      last  = oper  ;              // shift operator
      value = input ;              // shift number
    }
    else                           // reduce top
      value = operators[oper] (value, input) ;
  }

  var result  = stack ;
  if (result == 3 || result == 47 || result == 18)
    Debug.WriteLine ("{0}1{1}3{2}5{3}7{4}9 = {5}",
      (i & 0x100) != 0 ? "-" : "",
      opstrings[(i >> 0) & 3],
      opstrings[(i >> 2) & 3],
      opstrings[(i >> 4) & 3],
      opstrings[(i >> 6) & 3],
      result) ;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4679056

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档