小弟现在在做个工资公式编辑器 但是有些地方难住了小弟 现在先说明下效果一个公式分三种: 1.基本项 2.公式 3.SQL 1和3都属于值(就是他们只有值 没有其他的东西) 公式是负责运算值(公式里包含值 公式也可以包含其他公式 但是其他公式必须返回一个值)于是问题就来了 如果一开始我定义了一个基本项 他能够返回一个值 然后定义多个其他的公式 都使用了这个值 而再回头修改那个基本项 把他变成公式 并使用一个使用该基本项(就是变成公式的基本项)的有返回值的公式(就像一个圈..) 这种情况如何避免 我之前的前辈是根据是设置运算时间超过一定时限之后便告诉用户运算失败 但是我不希望还是以这种方式来解决这个问题了运算方式是利用递归

解决方案 »

  1.   

    没看懂!!哇哈哈!{公式({基本项})}基本项引用变成{公式()},COPY 原基本项--重命名为公式。置换公式 需要 更改的基本项,递归在扫寻的时候就是深度扫描呀!
      

  2.   

    还没有开始运算就要估计出运算的结果,这个好像不太可能。或许换个别的思路不用这样的1.基本项 2.公式 3.SQL 设计思路呢。
      

  3.   


    不一定是基本项变公式 我先说明一下其实总体来说 所有的公式只有两个区别 一个是可以返回值 一个是不可以返回值 于是几条规律就出现了1.基本项肯定可以返回值(因为基本项本身就是值)
    2.使用基本项的公式也肯定能返回值(因为公式里除了基本项就是常量 基本项是他们运算的必须品 没有基本项的公式除非全部是常量 否则是无法进行运算的)
    3.使用有返回值的公式的公式也肯定有返回值 其实规则同上我现在区分一个公式是否有返回值这容易 但是 假设A 使用B B使用C C使用D A是基本项 ABCD都有返回值 但是如果这期间把A变成了个公式 并且引用其他有返回值的公式 比如B 那么就会出现个循环 原本是利用运算时间来判断是否走入死循环 但现在不想这么做 这回明白没?(SQL也类似基本项 返回一个值)
      

  4.   

    奇怪为什么基项要变成公式……
    假如A基项,B公式(使用A,有返回值)。
    如果你更改A为公式(使用B)。
    那更改后B里的A你希望的是仍然是之前的A的值?还是改变后的A值?
    你的A值所想要使用的B值是之前的B值?还是死循环的B值?
    如更改前:
    A: 1 B:2 * A
    更改后:
    A: B * 2,这个B是指多少?
      

  5.   

    创建公式A时,遍历A的参数,如果A存在于参数B的参数表中,报循环错误,否则,将B的参数表添加到A的参数表中。
      

  6.   

    a->b->a 你这个能返回的了么?
      

  7.   


    不分简单还是不简单 只有两种状态 一种正常的 一种不正常的 如何区分是正常还不正常的 前期创建容易判断 但是后期修改 尤其是修改之前创建的公式并且被一大堆公式使用了的公式该如何去解决 正常途径的解决办法是查找每个查询每个使用了该公式的公式 并且避免该公式使用那些公式 但是这种办法不可行 因为有些公式隐式的使用了该公式(比如说公式A使用了公式B 公式B里使用了公式C C里又使用了 没有直接关系 但是他们的确是有联系的)
      

  8.   


    在java里递归调用也是很常见的。但是运行时变量状态等原因,没有办法判断是不是一个可以正常退出的递归。我想你这个和java里的这种情况很类似,所以可能没有什么办法。
      

  9.   

    - -
    麻烦楼主多看看,再说话!
    创建公式A时,遍历A的参数,如果A存在于参数B的参数表中,报循环错误,否则,将B的参数表添加到A的参数表中。
    你所谓的套用的公式是怎么创建的!!!!
      

  10.   

    请楼主按照我提到的规则自行推演参数表,谢谢
    D = 2;
    E = 3;
    C = 2 * D + E; // C参数表?
    B = 2 * C; // B参数表?
    A = 2 * B + C; // A参数表?
      

  11.   


    ...偶又乱创建名词了 字面意思假设A公式使用了B公式和C公式而D公式用了A公式B公式用了D公式他们没有直接互相使用 而是通过一个其他的东西去使用
      

  12.   

    那你通过这些公式引用的回路不就可以判断了么?a->b a->c d->a b->  这就有回路,只不过回路上有3个节点。
      

  13.   

    a->b a->c
    d->a
    b->d扫描所有的变量,当扫描到a时,可以发现a->b ,b->d ,d->a 也就是一个回路。判断这个就是无法返回的。
      

  14.   

    公式->基本项+公式|SQL+公式|+|-|*|/|+公式|-公式|*公式|/公式.
      

  15.   

    LZ 需要解决的是循环引用的问题吧。可以参考Excel,引入概念:
    直接依赖:通过从字面分析公式X,可以得出X有哪些直接依赖。例如:X=a+b*2,那么X的直接依赖就是a、b建立一个list,这个list包含所有需要计算的公式,每个公式都有一个flag表示该公式是否被计算过for (count=0;count!=0;)
    {
        count=0;
        foreach (formula in list)
        {
            if (formula.flag==true) continue;
            if (formula所直接依赖的公式都被计算过)
            {
                则计算该formula的值,并将其flag置为true(表示被计算过);
                count++;
            }
        }
    }
    如果上述代码执行完仍有公式没有被计算,则说明存在循环引用的情况
      

  16.   

    代码有点问题改成for (;;)
    {
        count=0;
        foreach (formula in list)
        {
            if (formula.flag==true) continue;
            if (formula所直接依赖的公式都被计算过)
            {
                则计算该formula的值,并将其flag置为true(表示被计算过);
                count++;
            }
        }
        if (count!=0) break;
    }
      

  17.   


    这里不需要获得间接依赖。
    例如x=a+b,a=b+c,b=c+a,c=2
    一开始list是这样
    公式名,公式,flag,直接依赖项(使用|做分割符)
    x,a+b,0,a|b
    a,b+c,0,b|c
    b,c+a,0,a|c
    c,2,0,空
    第一次遍历list,由于x,a,b的直接依赖项都没有算出来,所以直接把c计算了,于是list变成
    x,a+b,0,a|b
    a,b+c,0,b|c
    b,c+a,0,a|c
    c,2,1,空
    第二次遍历,由于a|b没有计算所以x算不出,由于b没有计算所以a算不出,由于a没有计算所以b算不出
    这次遍历总共算了0个公式,退出循环
    这时还有3个公式没有算,说明这3个公式间存在循环引用
      

  18.   

    如果把公式改为x=a+b,a=b+c,b=c*2,c=2
    一开始list是这样 
    公式名,公式,flag,直接依赖项(使用|做分割符) 
    x,a+b,0,a|b 
    a,b+c,0,b|c 
    b,c*2,0,c 
    c,2,0,空 
    第一次遍历list,由于x,a,b的直接依赖项都没有算出来,所以直接把c计算了,于是list变成 
    x,a+b,0,a|b 
    a,b+c,0,b|c 
    b,c*2,0,c 
    c,2,1,空 
    第二次遍历list可以计算出b,list变成
    x,a+b,0,a|b 
    a,b+c,0,b|c 
    b,c*2,1,c 
    c,2,1,空 
    第三次遍历list可以计算出a,list变成
    x,a+b,0,a|b 
    a,b+c,1,b|c 
    b,c*2,1,c 
    c,2,1,空 
    第四次遍历list可以计算出x,list变成
    x,a+b,1,a|b 
    a,b+c,1,b|c 
    b,c*2,1,c 
    c,2,1,空 
    这时所有公式都计算完毕了。
    上面的算法还有优化的空间的,比如做2个list,一个是还没有计算的公式的list,一个是计算完成的list,每次只要遍历没有计算的list就行了
      

  19.   

    css常用属性
      

  20.   

    如果把每个公式看作一个函数的话,你要避免这个函数意义上的递归调用。你可以维护一个正在计算的公式列表,当开始计算公式时把公式名写入,一旦这个公式计算出值则从列表中去掉。那么你只需要保证开始进入某公式时列表中没有正在计算的此公式。换个说法也许更容易理解:把所有不同的公式看作是不同的括号对(比如{},[],()).你的要求是当同一种括号不能嵌套。比如A=B+C, C = A + 1. ABC分别对应{[(.则有以下括号序列{[]({ -- 发现问题!。
    如果用栈来实现的话,还可以检查你的程序过程是否正确,因为右括号出现时必须匹配最后的一个左括号。比如这样的序列{[}就说明调用过程有问题。