【问题标题】:Sign of a symbolic algebraic expression符号代数表达式的符号
【发布时间】:2014-01-10 19:27:53
【问题描述】:

是否有任何算法可以找到“树 - 形式”中给出的任意符号代数表达式的符号?

我知道不存在通用算法,因为零识别问题对于任意表达式是不可判定的,但是我应该如何解决寻找表达式符号的问题? (这在计算机代数中是如何完成的?)

例如:sign(sqrt(2)-1) = ?

【问题讨论】:

  • 当你说“代数”时,它是否包含未知数?
  • 不,它没有变量。另外,当我说“代数”时,我并不是说它只能包含代数。它还可以包含 log(2) 或 atan(2) 之类的内容。但我不是在寻找通用算法。
  • 您应该以足够的精度评估表达式。您可能想要使用任意精度的算术包,并可能在此之上使用区间算术。
  • 我在想这个,但是如果这个数字太小以至于它评估为数字“0”怎么办。一个更大的问题是表达式的评估需要时间(有时太多时间)
  • 有些问题在数值上是困难的,你不会轻易解决这个问题(如果你这样做的话)。如果数字如此接近 0,那差异可能小于 machine-epsilon,我相信可能没有解决方案。

标签: algorithm algebra computer-algebra-systems


【解决方案1】:

评估函数值

你需要函数评估引擎(它并不难编码)如果你想支持 +,没有办法评估 sign only ,- 操作!!!我所有的函数评估器都是这样工作的:

  1. 编译函数的源代码

    首先创建支持的函数表(id、操作数、名称、指向函数的指针),例如:

    +,-,*,/,sin,cos,....
    

    这些将是您需要评估的任何受支持表达式的构建块。不要忘记在您的代码中编写所有函数。处理括号 (,) 也作为函数 (push,pop)。按操作数的数量对函数进行分组,因此 +,- 有 1 个和 2 个操作数(每个有两个不同的函数!!!)。

    现在从表达式中提取:

    • 变量名
    • 常量名称和值
    • 数值

    进入某种表格/列表:

    variables[](id,name,value)
    constants[](id,name,value)
    numbers  [](id,    ,value)
    

    现在终于构造编译函数字符串了。我的字符串由两个 int 组成。第一个是type(使用哪个表),第二个是id(表中的索引)。

    例如表达式:

    sign(sqrt(2)-1)
    

    类型:

    id type
    0  function
    1  number
    2  constant
    3  variable
    

    功能:

    id name   pointer
    0  '('    ???
    1  ')'    ???
    2  '+'    ???
    3  '-'    ???
    4  '*'    ???
    5  '/'    ???
    6  'sqrt' ???
    7  'sign' ???
    

    没有变量常量数字是:

    id value
    0  2  
    1  1
    

    编译后的字符串:

    type id
    0    7   // sign(1 operand)
    0    6   // sqrt(1 operand)
    1    0   // 2
    0    3   // - (2 operands)
    1    1   // 1
    
  2. 编译后你需要解释字符串并评估它的值。

    1. 初始化变量

      op1=0`,`op2=0, // set all operands to zero (number depends on supported functions usually 2)
      opn=0          // actual operands number
      fx=none        // actual function (for example none=-1)
      fxn=0          // actual function operands number
      
    2. 读取已编译字符串的第一条记录

      如果它是值(数字、常量、变量),则使用它设置适当的op? 值并递增操作数计数器opn++

      如果是函数集fx,fxn 带有它的代码

    3. 如果opn == fxn

      您已达到所需的操作数计数,因此执行函数 fx 并初始化下一个函数

      op1=fxtab[fx].pointer(op1,op2,...)
      fx=none,fxn=1
      opn=1  (some spec functions can return more operands, then set op1,op2,.. opn=...)
      
    4. 如果不是字符串结尾转到 #2 但有下一个字符串记录

    5. 最后op1 应该保留你的输出值

一些示例函数(C++ 实现):

double sign(double op1) 
 { 
 if (op1>0.0) return +1.0; 
 if (op1<0.0) return -1.0; 
 return 0.0; 
 }
double sqrt1(double op1) { return sqrt(op1); }
double plus1(double op1) { return op1; }
double minus1(double op1) { return -op1; }
double plus2(double op1,double op2) { return op1+op2; }
double minus2(double op1,double op2) { return op1-op2; }

[备注]

您必须处理像function = ""; 这样的特殊情况。还要注意空格、区分大小写,因为编译中的任何错误都会使结果无效。

速度不是一个大问题,这是解释评估而不是数值解决方案。所有操作的调用时间与您在纸上执行的时间相同。

您还应该处理数学错误(溢出、无效操作数、NaNInf ...)

我通常将具有相同数量的操作数的函数分组为自己的类型以简化事情

【讨论】:

  • 我已经有一个字符串表达式的数字和符号解析器。但是我想知道这是如何在计算机代数(如 Mathematica 或 Maple)中完成的。这真的是通过表达式的数值来完成的吗?
  • 我认为是的,因为如果你在公式中有加法或减法,那么符号是由符号和操作数的值定义的......所以我认为没有其他方法可以做到这一点决心
猜你喜欢
  • 1970-01-01
  • 2015-01-28
  • 2016-09-12
  • 1970-01-01
  • 2014-07-17
  • 2014-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多