⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 muparsertest.cpp

📁 Mathematical expressions parser library
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    // distinguish constants with same basename
	  iStat += EqnTest("const", 1, true);
	  iStat += EqnTest("const1", 2, true);
	  iStat += EqnTest("const2", 3, true);
	  iStat += EqnTest("2*const", 2, true);
	  iStat += EqnTest("2*const1", 4, true);
	  iStat += EqnTest("2*const2", 6, true);
	  iStat += EqnTest("2*const+1", 3, true);
	  iStat += EqnTest("2*const1+1", 5, true);
	  iStat += EqnTest("2*const2+1", 7, true);
	  iStat += EqnTest("const", 0, false);
	  iStat += EqnTest("const1", 0, false);
	  iStat += EqnTest("const2", 0, false);

    // distinguish variables with same basename
	  iStat += EqnTest("a", 1, true);
    iStat += EqnTest("aa", 2, true);
    iStat += EqnTest("2*a", 2, true);
	  iStat += EqnTest("2*aa", 4, true);
	  iStat += EqnTest("2*a-1", 1, true);
	  iStat += EqnTest("2*aa-1", 3, true);

    // Finally test querying of used variables
    try
    {
      int idx;
      mu::Parser p;
      mu::value_type vVarVal[] = { 1, 2, 3, 4, 5};
      p.DefineVar("a", &vVarVal[0]);
      p.DefineVar("b", &vVarVal[1]);
      p.DefineVar("c", &vVarVal[2]);
      p.DefineVar("d", &vVarVal[3]);
      p.DefineVar("e", &vVarVal[4]);

      // Test lookup of defined variables
      // 4 used variables
      p.SetExpr("a+b+c+d");
      mu::varmap_type UsedVar = p.GetUsedVar();
      int iCount = (int)UsedVar.size();
      if (iCount!=4) throw false;

      mu::varmap_type::const_iterator item = UsedVar.begin();
      for (idx=0; item!=UsedVar.end(); ++item)
      {
        if (&vVarVal[idx++]!=item->second) 
          throw false;
      }

      // Test lookup of undefined variables
      p.SetExpr("undef1+undef2+undef3");
      UsedVar = p.GetUsedVar();
      iCount = (int)UsedVar.size();
      if (iCount!=3) throw false;

      for (item = UsedVar.begin(); item!=UsedVar.end(); ++item)
      {
        if (item->second!=0) 
          throw false; // all pointers to undefined variables must be null
      }

      // 1 used variables
      p.SetExpr("a+b");
      UsedVar = p.GetUsedVar();
      iCount = (int)UsedVar.size();
      if (iCount!=2) throw false;
      item = UsedVar.begin();
      for (idx=0; item!=UsedVar.end(); ++item)
        if (&vVarVal[idx++]!=item->second) throw false;

    }
    catch(...)
    {
      iStat += 1;
    }

	if (iStat==0)  
      *m_stream << "passed" << endl;
	else
      *m_stream << "\n  failed with " << iStat << " errors" << endl;

    return iStat;
  }

  //---------------------------------------------------------------------------
  int ParserTester::TestMultiArg()
  {
    int iStat = 0;
    *m_stream << "testing multiarg functions...";
    
    // picking the right argument
	iStat += EqnTest("f1of1(1)", 1, true);
	iStat += EqnTest("f1of2(1, 2)", 1, true);
	iStat += EqnTest("f2of2(1, 2)", 2, true);
	iStat += EqnTest("f1of3(1, 2, 3)", 1, true);
	iStat += EqnTest("f2of3(1, 2, 3)", 2, true);
	iStat += EqnTest("f3of3(1, 2, 3)", 3, true);
	iStat += EqnTest("f1of4(1, 2, 3, 4)", 1, true);
	iStat += EqnTest("f2of4(1, 2, 3, 4)", 2, true);
	iStat += EqnTest("f3of4(1, 2, 3, 4)", 3, true);
	iStat += EqnTest("f4of4(1, 2, 3, 4)", 4, true);
	iStat += EqnTest("f1of5(1, 2, 3, 4, 5)", 1, true);
	iStat += EqnTest("f2of5(1, 2, 3, 4, 5)", 2, true);
	iStat += EqnTest("f3of5(1, 2, 3, 4, 5)", 3, true);
	iStat += EqnTest("f4of5(1, 2, 3, 4, 5)", 4, true);
	iStat += EqnTest("f5of5(1, 2, 3, 4, 5)", 5, true);
	// Too few arguments / Too many arguments
	iStat += EqnTest("f1of1(1,2)", 0, false);
	iStat += EqnTest("f1of1()", 0, false);
	iStat += EqnTest("f1of2(1, 2, 3)", 0, false);
    iStat += EqnTest("f1of2(1)", 0, false);
	iStat += EqnTest("f1of3(1, 2, 3, 4)", 0, false);
    iStat += EqnTest("f1of3(1)", 0, false);
	iStat += EqnTest("f1of4(1, 2, 3, 4, 5)", 0, false);
    iStat += EqnTest("f1of4(1)", 0, false);
	iStat += EqnTest("(1,2,3)", 0, false);
	iStat += EqnTest("1,2,3", 0, false);
	iStat += EqnTest("(1*a,2,3)", 0, false);
	iStat += EqnTest("1,2*a,3", 0, false);
     
	// correct calculation of arguments
	iStat += EqnTest("min(a, 1)",  1, true);
	iStat += EqnTest("min(3*2, 1)",  1, true);
	iStat += EqnTest("min(3*2, 1)",  6, false);
	// correct calculation of arguments
	iStat += EqnTest("min(3*a+1, 1)",  1, true);
	iStat += EqnTest("max(3*a+1, 1)",  4, true);
	iStat += EqnTest("max(3*a+1, 1)*2",  8, true);
	iStat += EqnTest("2*max(3*a+1, 1)+2",  10, true);

    // functions with Variable argument count
	iStat += EqnTest("sum(1,2,3)",  6, true);
	iStat += EqnTest("2*sum(1,2,3)",  12, true);
	iStat += EqnTest("2*sum(1,2,3)+2",  14, true);
	iStat += EqnTest("2*sum(-1,2,3)+2",  10, true);
	iStat += EqnTest("2*sum(-1,2,-(-a))+2",  6, true);
	iStat += EqnTest("2*sum(-1,10,-a)+2",  18, true);
	iStat += EqnTest("2*sum(1,2,3)*2",  24, true);
	iStat += EqnTest("sum(1,-max(1,2),3)*2",  4, true);
	iStat += EqnTest("sum(1*3, 4, a+2)",  10, true);
	iStat += EqnTest("sum(1*3, 2*sum(1,2,2), a+2)",  16, true);
	iStat += EqnTest("sum(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2)", 24, true);

    // some failures
    iStat += EqnTest("sum()",  0, false);
	iStat += EqnTest("sum(,)",  0, false);
	iStat += EqnTest("sum(1,2,)",  0, false);
	iStat += EqnTest("sum(,1,2)",  0, false);

	if (iStat==0) 
      *m_stream << "passed" << endl;
	else
      *m_stream << "\n  failed with " << iStat << " errors" << endl;

    return iStat;
  }


  //---------------------------------------------------------------------------
  int ParserTester::TestInfixOprt()
  {
    int iStat = 0;
    *m_stream << "testing infix operators...";

	  iStat += EqnTest("-1",    -1, true);
	  iStat += EqnTest("-(-1)",  1, true);
    iStat += EqnTest("-(-1)*2",  2, true);
	  iStat += EqnTest("-(-2)*sqrt(4)",  4, true);
	  iStat += EqnTest("-a",  -1, true);
    iStat += EqnTest("-(a)",  -1, true);
	  iStat += EqnTest("-(-a)",  1, true);
	  iStat += EqnTest("-(-a)*2",  2, true);
	  iStat += EqnTest("-(8)", -8, true);
	  iStat += EqnTest("-8", -8, true);
	  iStat += EqnTest("-(2+1)", -3, true);
	  iStat += EqnTest("-(f1of1(1+2*3)+1*2)", -9, true);
	  iStat += EqnTest("-(-f1of1(1+2*3)+1*2)", 5, true);
	  iStat += EqnTest("-sin(8)", -0.989358, true);
	  iStat += EqnTest("3-(-a)", 4, true);
	  iStat += EqnTest("3--a", 4, true);
  
    // Postfix / infix priorities
    iStat += EqnTest("~2#", 12, true);
    iStat += EqnTest("~f1of1(2)#", 12, true);
    iStat += EqnTest("~(b)#", 12, true);
    iStat += EqnTest("(~b)#", 12, true);
    iStat += EqnTest("~(2#)", 8, true);
    iStat += EqnTest("~(f1of1(2)#)", 8, true);

	  if (iStat==0)
      *m_stream << "passed" << endl;
	  else
      *m_stream << "\n  failed with " << iStat << " errors" << endl;

    return iStat;
	}


	//---------------------------------------------------------------------------
	int ParserTester::TestPostFix()
	{
    int iStat = 0;
    *m_stream << "testing postfix operators...";

	  // application
	  iStat += EqnTest("3m+5", 5.003, true);
	  iStat += EqnTest("1000m", 1, true);
	  iStat += EqnTest("1000 m", 1, true);
	  iStat += EqnTest("(a)m", 1e-3, true);
	  iStat += EqnTest("-(a)m", -1e-3, true);
	  iStat += EqnTest("-2m", -2e-3, true);
	  iStat += EqnTest("f1of1(1000)m", 1, true);
	  iStat += EqnTest("-f1of1(1000)m", -1, true);
	  iStat += EqnTest("-f1of1(-1000)m", 1, true);
	  iStat += EqnTest("f4of4(0,0,0,1000)m", 1, true);
	  iStat += EqnTest("2+(a*1000)m", 3, true);
    // some incorrect results
	  iStat += EqnTest("1000m", 0.1, false);
	  iStat += EqnTest("(a)m", 2, false);
	  // failure due to syntax checking
	  iStat += EqnTest("a m", 0, false);
	  iStat += EqnTest("4 + m", 0, false);
	  iStat += EqnTest("m4", 0, false);
	  iStat += EqnTest("sin(m)", 0, false);
	  iStat += EqnTest("m m", 0, false);
	  iStat += EqnTest("m(8)", 0, false);
	  iStat += EqnTest("4,m", 0, false);
	  iStat += EqnTest("-m", 0, false);
	  iStat += EqnTest("2(-m)", 0, false);
	  iStat += EqnTest("2(m)", 0, false);

	  if (iStat==0)
      *m_stream << "passed" << endl;
	  else
      *m_stream << "\n  failed with " << iStat << " errors" << endl;

    return iStat;
	}

	//---------------------------------------------------------------------------
	/** \brief Test volatile (nonoptimizeable functions). */
  int ParserTester::TestVolatile()
	{
      int iStat = 0;
      *m_stream << "testing volatile/nonvolatile functions...";

      // First test with volatile flag turned on
      try
      {

        mu::Parser p;
        p.DefineFun("rnd", Rnd, false);
        p.DefineFun("valueof", RndWithString, false);

        // 1st test, compare results from sucessive calculations
        p.SetExpr("3+rnd(8)");
        if (p.Eval()==p.Eval()) iStat += 1;

        // 2nd test, force bytecode creation, compare two results both 
        // calculated from bytecode
        p.SetExpr("3+rnd(8)"); 
        p.Eval(); //<- Force bytecode creation
        if (p.Eval()==p.Eval()) iStat += 1;

        p.SetExpr("3*rnd(8)+3");
        p.Eval(); //<- Force bytecode creation
        if (p.Eval()==p.Eval()) iStat += 1;

        p.SetExpr("10+3*sin(rnd(8))-1");
        p.Eval(); //<- Force bytecode creation
        if (p.Eval()==p.Eval()) iStat += 1;

        p.SetExpr("3+rnd(rnd(8))*2");
        p.Eval(); //<- Force bytecode creation
        if (p.Eval()==p.Eval()) iStat += 1;

        p.SetExpr("valueof(\"Das ist ein Test\")");
        p.Eval(); //<- Force bytecode creation
        if (p.Eval()==p.Eval()) iStat += 1;
      }
      catch(Parser::exception_type &e)
      {
        *m_stream << "\n  " << e.GetExpr() << " : " << e.GetMsg();
        iStat += 1;
      }


      // Second test with volatile flag turned off
      try
      {
        mu::Parser p;
        p.DefineFun("rnd", Rnd);
        p.DefineFun("valueof", RndWithString);

        // compare string parsing with bytecode
        p.SetExpr("3+rnd(8)"); 
        if (p.Eval()!=p.Eval()) iStat += 1;

        p.SetExpr("3+rnd(8)"); 
        p.Eval(); //<- Force bytecode creation
        if (p.Eval()!=p.Eval()) iStat += 1;

        p.SetExpr("3*rnd(8)+3");
        p.Eval(); //<- Force bytecode creation
        if (p.Eval()!=p.Eval()) iStat += 1;

        p.SetExpr("10+3*sin(rnd(8))-1");
        p.Eval(); //<- Force bytecode creation
        if (p.Eval()!=p.Eval()) iStat += 1;

        p.SetExpr("3+rnd(rnd(8))*2");
        p.Eval(); //<- Force bytecode creation
        if (p.Eval()!=p.Eval()) iStat += 1;

        p.SetExpr("valueof(\"Das ist ein Test\")");
        p.Eval(); //<- Force bytecode creation
        if (p.Eval()!=p.Eval()) iStat += 1;
      }
      catch(Parser::exception_type &e)
      {
        *m_stream << "\n  " << e.GetExpr() << " : " << e.GetMsg();
        iStat += 1;
      }
      
      if (iStat==0)
        *m_stream << "passed" << endl;
	    else
        *m_stream << "\n  failed with " << iStat << " errors" << endl;

      return iStat;
	}

	//---------------------------------------------------------------------------
	int ParserTester::TestFormula()
	{
      int iStat = 0;
      *m_stream << "testing sample formulas...";

      // operator precedencs
  	  iStat += EqnTest("1+2-3*4/5^6", 2.99923, true);
	    iStat += EqnTest("1^2/3*4-5+6", 2.3333, true);
	    iStat += EqnTest("1+2*3", 7, true);
	    iStat += EqnTest("1+2*3", 7, true);
	    iStat += EqnTest("(1+2)*3", 9, true);
	    iStat += EqnTest("(1+2)*(-3)", -9, true);
      iStat += EqnTest("2/4", 0.5, true);

	    iStat += EqnTest("exp(ln(7))", 7, true);
	    iStat += EqnTest("e^ln(7)", 7, true);
	    iStat += EqnTest("e^(ln(7))", 7, true);
	    iStat += EqnTest("(e^(ln(7)))", 7, true);
	    iStat += EqnTest("1-(e^(ln(7)))", -6, true);
	    iStat += EqnTest("2*(e^(ln(7)))", 14, true);
      iStat += EqnTest("10^log(5)", 5, true);
      iStat += EqnTest("10^log10(5)", 5, true);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -