【问题标题】:Java: Stringtokenizer To ArrayJava:Stringtokenizer 到数组
【发布时间】:2015-10-06 01:10:16
【问题描述】:

给定一个多项式,我正在尝试编写代码来创建一个多项式,该多项式按次数计算,并将相似的项加在一起例如...给定

String term = "323x^3+2x+x-5x+5x^2" //Given
What I'd like = "323x^3+5x^2-2x" //result

到目前为止,我已经用这个标记了给定的多项式......

    term = term.replace("+" , "~+");
    term = term.replace("-", "~-");
    System.out.println(term);
    StringTokenizer multiTokenizer = new StringTokenizer(term, "~");
    int numberofTokens = multiTokenizer.countTokens();
    String[] tokensArray = new String[numberofTokens];
    int x=0;
    while (multiTokenizer.hasMoreTokens())
    {

        System.out.println(multiTokenizer.nextToken());

    }

导致

323x^3~+2x~+x~-5x~+5x^2
323x^3
+2x
+x
-5x
+5x^2

我将如何从 x 值中拆分系数,将每个系数保存在一个数组中,然后将度数放入具有与其系数相同索引的不同数组中?然后我将使用这个算法来添加类似的术语......

for (i=0;i<=biggest_Root; i++)
     for(j=0; j<=items_in_list ; j++)
          if (degree_array[j] = i)
               total += b1[j];
     array_of_totals[i] = total;

非常感谢任何和所有帮助!

【问题讨论】:

  • 我不太明白你的问题

标签: java arrays int polynomial-math stringtokenizer


【解决方案1】:

您还可以更新项,使它们都有系数:

s/([+-])x/\11/g

所以+x^2 变成+1x^2。

您的个人系数可以通过简单的正则表达式提取。 这样的事情就足够了:

/([+-]?\d+)x/     // match for x
/([+-]?\d+)x\^2/   // match for x^2
/([+-]?\d+)x\^3/   // match for x^3
/([+-]?\d+)x\^4/   // match for x^4

然后

sum_of_coefficient[degree] += match

其中“match”是正则表达式匹配的 parseInt(系数为 1 且没有数字的特殊情况,例如 +x)

sum_of_coefficient[3] = 323
sum_of_coefficient[1] = +2+1-5 = -2
sum_of_coefficient[2] = 5

【讨论】:

    【解决方案2】:

    使用“正则表达式”模式来简化解析

    (让代码更酷更简洁)

    这是一个工作示例,它根据您目前已解析的术语为每个术语解析系数、变量和度数。它只是将示例中显示的术语插入到字符串列表中,然后以相同的方式处理每个字符串。

    这个程序运行并产生输出,如果你喜欢它,你可以将它拼接到你的程序中。试试看:

    $ javac parse.java

    $java 解析

    限制和潜在改进:

    从技术上讲,系数和度数可以是分数,因此可以很容易地更改正则表达式来处理这些数字。然后你可以使用 Float.parseFloat() 代替 Integer.parseInt() 来将匹配的值转换为你可以使用的变量。

    import java.util.*;
    import java.util.regex.*;
    
    public class parse {
        public static void main(String args[]) {
    
            /* 
             * Substitute this List with your own list or
             * array from the code you've written already...
             *
             * vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv */
    
            List<String>terms = new ArrayList<String>();
            terms.add("323x^3");
            terms.add("+2x");
            terms.add("+x");
            terms.add("-5x");
            terms.add("+5x^2");
    
            /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
    
            for (String term : terms) {
    
                System.out.print("Term: " + term + ": \n");
    
                Pattern pattern = Pattern.compile("([+-]*\\d*)([A-Za-z]*)\\^*(\\d*)"); 
                Matcher matcher = pattern.matcher(term);
    
                if (matcher.find()) {
    
                    int coefficient = 1;
                    try {
                        coefficient = Integer.parseInt(matcher.group(1));
                    } catch (Exception e) {}
    
                    String variable = matcher.group(2);
    
                    int degree = 1;
                    try { 
                        degree = Integer.parseInt(matcher.group(3));
                    } catch (Exception e) {}
    
                    System.out.println("   coefficient = " + coefficient);
                    System.out.println("   variable    = " + variable);
                    System.out.println("   degree      = " + degree);
    
                    /* 
                     * Here, do what you need to do with
                     *     variable, coefficient and degree 
                     */ 
    
                } 
            }
        }
    }
    

    示例代码中正则表达式的解释:

    这是使用的正则表达式:

    ([+-]*\\d*)([A-Za-z]*)\\^*(\\d*)
    

    每个带括号的部分代表我想要匹配并提取到结果中的术语的一部分。它将匹配的任何内容放入与括号集相对应的组中。第一组括号进入第 1 组,第二组进入第 2 组,依此类推...

    1. 第一个匹配器(由( )分组)是([+-]*\\d*) 设计匹配(例如提取)系数(如果有)并将其放入第 1 组。它期望出现零个或多个“+”或“-”字符,后跟零个或多个数字。我可能应该写成 [+-]?\\d* 匹配 zeroone +- 字符。

    2. 下一个分组匹配器是([A-Za-z]*),表示匹配零个或多个大写或小写字母。 这是试图提取变量名(如果有)并将其放入第 2 组。

    3. 接着,有一个未分组的\\^*,它匹配0个或多个^字符。它没有分组在括号中,因为我们想说明文本中的 ^ 字符,但不将其存储在任何地方。我们对它后面的指数非常感兴趣。 注意:两个反斜杠是在 Java 字符串中创建一个反斜杠的方式。我们试图表示的真实世界正则表达式是\^*。它在这里被转义的原因是因为^ 未转义在正则表达式中具有特殊含义,但我们只想匹配/允许实际插入符号^ 在我们正在解析的代数项中的那个位置的可能性。

    4. 最终的模式组是(\\d*)。在字符串文字之外,就像大多数正则表达式一样,它只是\d*。它被转义了,因为在默认情况下,在正则表达式中,d,未转义,表示匹配文本中当前位置的 literal d,但是,转义,\d 是一个特殊的正则表达式匹配任何数字 [0-9] 的模式(正如 Pattern javadoc 解释的那样)。 * 表示在该点期望(匹配)零个或多个数字。或者,+ 表示在当前位置的文本中预期有 1 个或多个数字,? 意味着在当前位置的文本中预期有 0​​ 或 1 个数字。因此,本质上,最后一组旨在匹配并提取可选插入符号后的指数(如果有),将该数字放入第 3 组。

    记住( )(带括号的)分组只是为了让我们可以将这些区域提取到单独的组中。

    如果这一切都不完全合理,请学习一般的正则表达式并在线阅读 Java Pattern 类 javadoc。它们并不像初看起来那么可怕,而且对于任何程序员来说都是非常值得尽快学习的,因为它跨越了最流行的脚本语言和编译器,所以学习一次,你就会拥有一个非常强大的工具。

    【讨论】:

    • 您能解释一下模式和匹配器的工作原理吗?我对此有点困惑,例如,如果一个数字没有任何变量,我将如何将变量设置为 NULL?
    • 我更新了文本来解释我写的Pattern 是如何工作的。一般阅读Regular Expressions。并查找使用 Pattern 的 Java 示例代码以获得更多帮助。我认为如果省略 x,匹配应该会起作用。请参阅上面我的文章第 2 节中的描述。它旨在允许没有变量名。最好的办法是编译它并进行实验。您可以更改代码中的术语并使用基于 Pattern javadocs 的正则表达式。祝你好运!
    • 惊人的细节,我非常感谢你。最后一个问题,将字符串标记器中的标记放入数组列表中,是否像创建一个新的数组列表并循环执行terms.add(StringTokenizer.next())一样简单?
    • 只要 StringTokenizer() 返回一个 String 就可以了。但是您不需要使用 ArrayList(List 的子类),我这样做只是因为它是一种将事物存储在列表中的非常方便的方法,并且我想将您的数据插入代码中。你可以用for (String term : StringTokenizer.next())之类的东西替换它,如果它返回正确提取的术语,就像我在列表中放入的那样,用于下一阶段的解析..顺便说一句:如果这个答案解决了它或给你一个想要的方法,你可以点击√ 旁边的答案?谢谢!
    【解决方案3】:

    这看起来像是一个家庭作业问题,所以我不会在这里透露整个答案,但这是我开始的方法

    public class Polynomial {
    
    private String rawPolynomial;
    private int lastTermIndex = 0;
    private Map<Integer, Integer> terms = new HashMap<>();
    
    public Polynomial(String poly) {
        this.rawPolynomial = poly;
    }
    
    public void simplify() {
        while(true){
            String term = getNextTerm(rawPolynomial);
            if ("".equalsIgnoreCase(term)) {
                return;
            }
            Integer degree = getDegree(term);
            Integer coeff = getCoefficient(term);
            System.out.println(String.format("%dx^%d", coeff, degree));
            terms.merge(degree, coeff, Integer::sum);
        }
    }
    
    private String getNextTerm(String poly) {
    ...
    }
    
    private Integer getDegree(String poly) {
        ...
    }
    
    private Integer getCoefficient(String poly) {
        ...
    }
    
    @Override public String toString() {
        return terms.toString();
    }
    }
    

    还有一些测试可以帮助您入门 -

    public class PolynomialTest {
        @Test public void oneTermPolynomialRemainsUnchanged() {
            Polynomial poly = new Polynomial("3x^2");
            poly.simplify();
            assertTrue("3x^2".equalsIgnoreCase(poly.toString()));
        }
    
    }
    

    你应该能够填空,希望这会有所帮助。如果您遇到困难,我很乐意为您提供进一步的帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-11-13
      • 2018-05-19
      • 1970-01-01
      • 2015-06-06
      • 2022-01-24
      • 2014-10-30
      • 1970-01-01
      相关资源
      最近更新 更多