【问题标题】:C++ extract polynomial coefficientsC++ 提取多项式系数
【发布时间】:2009-11-26 23:12:03
【问题描述】:

所以我有一个如下所示的多项式:-4x^0 + x^1 + 4x^3 - 3x^4
我可以通过空格和“+”将其标记为:-4x^0, x^1, 4x^3, -, 3x^4

我怎样才能得到带有负号的系数:-4、1、0、4、-3
x 是唯一会出现的变量,它总是按顺序出现
我计划将系数存储在数组中,数组索引为指数
所以:-4 将在索引 0 处,1 将在索引 1 处,0 在索引 2 处,4 在索引 3 处,-3 在索引 4 处

【问题讨论】:

  • 你也许应该选择 -4, 1, 0, 4, -3 这样你就有了所有指数(包括 2)的系数,或者创建一个额外的数组 0,1,3,4 来存储使用的指数。
  • 你的问题陈述很笼统......可以出现任何变量吗?总是x吗?条款总是按顺序排列的吗?
  • 类似于stackoverflow.com/questions/1801220/… ... 可能有澄清。

标签: c++ tokenize


【解决方案1】:

一旦您将标记化为“-4x^0”、“x^1”等,您就可以使用 strtol() 将文本表示形式转换为数字。 strtol 将自动在第一个非数字字符处停止,因此“x”将停止它; strtol 会给你一个指向停止它的字符的指针,所以如果你想偏执,你可以验证这个字符是一个 x。

您将需要处理隐含的 1(即特别在“x^1”中)。我会这样做:

long coeff;
if (*token == 'x')
{
   coeff = 1;
}
else
{
    char *endptr;
    coeff = strtol(token, &endptr, 10);
    if (*endptr != 'x')
    {
        // bad token
    }  
}

【讨论】:

  • 我尝试了这个,出于某种原因,当我将整数数组设置为 coeff 时,它会将所有内容都设置为 1。pastie.org/716637 任何人都可以看到有什么问题吗?
  • ^ 问题可能是我将 coeff (long int) 设置为 int 数组吗?
  • @Raptrex - 我的原始代码中有一个错误(你完全复制了它)。 if 表达式需要是 "if (*token == 'x')" 而不是 "if (*token = 'x')"。
【解决方案2】:
Start with "-4x^0 + x^1 + 4x^3 - 3x^4"
Split after ^number: "-4x^0", " + x^1", " + 4x^3", " - 3x^4"
Now everything behind an ^ is an exponent, everything before the x is an coefficient

编辑:获取系数的简单方法(包括符号):

Init coefficient with 0, sign with '+'
Go through each character before the x from left to right
  If it's a number ('0'..'9'), coefficient = coefficient * 10 + number
  If it's '-', set sign to '-'

【讨论】:

    【解决方案3】:

    扫描字符串中的“x”,然后向后存储系数的每个字符,直到找到空格。例如:

    for (int i=0; i<s.length(); ++i)
    {
        if (s[i] == 'x')
        {
            string c;
            for (int j=i-1; j>=0 && s[j]!=' '; --j)
                c = s[j] + c;
            cout << "coefficient: " << c << endl;
        }
    }
    

    【讨论】:

      【解决方案4】:

      对于一个快速的解决方案,我的方法是编写一个递归下降解析器。在字符串中向前移动并提取所需的组件。编写这样的表达式解析器的例子很多。

      如果你想使用一个库,你可以使用 boost::regex 或 boost::spirit,这取决于你想采用哪种方法。

      【讨论】:

        【解决方案5】:

        编写一个简单的分词器。定义一个数字标记 (/[-0123456789][0123456789]+/)、一个指数标记 (/x^(::number::)/)。忽略空格和+

        按照您的预期持续读取标记,直到字符串结束。然后以你想要的任何形式(例如整数)吐出标记。

        int readNumber(const char **input) {
            /* Let stdio read it for us. */
            int number;
            int charsRead;
            int itemsRead;
        
            itemsRead = sscanf(**input, "%d%n", &number, &charsRead);
        
            if(itemsRead <= 0) {
                // Parse error.
                return -1;
            }
        
            *input += charsRead;
        
            return number;
        }
        
        int readExponent(const char **input) {
            if(strncmp("x^", *input, 2) != 0) {
                // Parse error.
                return -1;
            }
        
            *input += 2;
        
            return readNumber(input);
        }
        
        /* aka skipWhitespaceAndPlus */
        void readToNextToken(const char **input) {
            while(**input && (isspace(**input) || **input == '+')) {
                ++*input;
            }
        }
        
        void readTerm(const char **input. int &coefficient, int &exponent, bool &success) {
            success = false;
        
            readToNextToken(input);
        
            if(!**input) {
                return;
            }
        
            coefficient = readNumber(input);
        
            readToNextToken(input);
        
            if(!**input) {
                // Parse error.
                return;
            }
        
            exponent = readExponent(input);
        
            success = true;
        }
        
        /* Exponent => coefficient. */
        std::map<int, int> readPolynomial(const char *input) {
            std::map<int, int> ret;
        
            bool success = true;
        
            while(success) {
                int coefficient, exponent;
        
                readTerm(&input, coefficient, exponent, success);
        
                if(success) {
                    ret[exponent] = coefficient;
                }
            }
        
            return ret;
        }
        

        这可能会在具有一些抽象的类中很好地进行(例如,从流中读取而不是从普通字符串中读取)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-08-23
          • 2012-11-05
          • 2019-07-05
          • 1970-01-01
          • 2022-11-26
          • 2014-12-30
          • 1970-01-01
          相关资源
          最近更新 更多