2016-02-13 10 views
0

Я не хочу решать уравнение, и мой вопрос не о структурах данных диаграмм и деревьев. Я пытаюсь создать Data Points для графика из уравнения, заданного пользователем. Я хочу эффективный алгоритм, простой в использовании и простой в обслуживании структуры данных. У меня есть два решения:Создать точки данных для графика из уравнения

1: Это тривиально и я видел во многих Приложениях.

String expr = "2*x+3*x"; 
Evaluator evaluator = new Evaluator();//I have this class 

for (int i = start; i < end; i += step) 
{ 
    evaluator.setConstant("x", i); 
    double ans = evaluator.evaluate(expr); 
} 

Это очень медленно, потому что каждый раз, когда каждый шаг повторяется как tokenzing, проверка, преобразования в RPN, готовя стеки и очереди и при расчете последнего результата. Возможное решение этой проблемы - это как-то кэширование всех стеков и очередей, но после этого потребуется сравнение между текущим выражением и предыдущим выражением для использования последнего сохраненного состояния.

2: В настоящее время я разрабатываю второе решение. Цель этого - эффективность и будет использоваться в Символических расчетах в будущем.

До сих пор моя реализация

Variable.java

import java.text.DecimalFormat; 

public class Variable 
{ 
    private final double pow; 
    private final double coefficient; 
    private final String symbol; 

    public Variable(String symbol) 
    { 
     this.symbol = symbol; 
     this.pow = 1.0; 
     this.coefficient = 1.0; 
    } 

    public Variable(String symbol, double coefficient, double pow)throws IllegalArgumentException 
    { 
     if (coefficient == 0.0)throw new IllegalArgumentException("trying to create variable with coefficient 0"); 
     if (pow == 0.0)throw new IllegalArgumentException("trying to create variable with exponent 0"); 

     this.symbol = symbol; 
     this.pow = pow; 
     this.coefficient = coefficient; 
    } 

    public final String getSymbol() 
    { 
     return this.symbol; 
    } 

    public final double getPow() 
    { 
     return this.pow; 
    } 

    public final double getCoefficient() 
    { 
     return this.coefficient; 
    } 

    @Override 
    public String toString() 
    { 
     StringBuilder builder = new StringBuilder(); 
     DecimalFormat decimalFormat = new DecimalFormat("#.############"); 
     if (coefficient != 1.0)builder.append(decimalFormat.format(this.coefficient)); 
     builder.append(this.symbol); 
     if (this.pow != 1.0)builder.append("^").append(decimalFormat.format(this.pow)); 

     return builder.toString(); 
    } 

    /* 
    * Stub Method 
    * Generate some unique hash code 
    * such that chances of key collision 
    * become less and easy to identify 
    * variables with same power and same 
    * symbol*/ 
    @Override 
    public int hashCode() 
    { 
     return 0; 
    } 
} 

Equation.java

import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.Iterator; 

public class Equation 
{ 
    private final ArrayList<Boolean> operations; 
    private final HashMap<String, Variable> variableHashMap; 
    private int typesOfVariables; 

    public Equation(Variable variable) 
    { 
     this.variableHashMap = new HashMap<>(); 
     this.operations = new ArrayList<>(); 
     this.typesOfVariables = 1; 

     this.variableHashMap.put(variable.getSymbol(), variable); 
    } 

    /*Stub Method*/ 
    public void addVariable(Variable variable, boolean multiply) 
    { 
     /* 
     * Currently not covering many cases 
     * 1: Add two variables which have same name 
     * and same pow. 
     * 2: variable which are wrapped inside functions e.g sin(x) 
     * and many other.*/ 
     if (multiply && variableHashMap.containsKey(variable.getSymbol())) 
     { 
      Variable var = variableHashMap.get(variable.getSymbol()); 
      Variable newVar = new Variable(var.getSymbol(), var.getCoefficient() * variable.getCoefficient(), var.getPow() + variable.getPow()); 
      /* 
      * Collision chances for variables with same name but 
      * with different powers*/ 
      this.variableHashMap.replace(var.getSymbol(), newVar); 
     } 
     else 
     { 
      ++this.typesOfVariables; 
      this.variableHashMap.put(variable.getSymbol(), variable); 
     } 
     this.operations.add(multiply); 
    } 

    /*Stub Method 
    *Value for every variable at any point will be different*/ 
    public double solveFor(double x) 
    { 
     if (typesOfVariables > 1)throw new IllegalArgumentException("provide values for all variables"); 

     Iterator<HashMap.Entry<String, Variable>> entryIterator = this.variableHashMap.entrySet().iterator(); 

     Variable var; 
     double ans = 0.0; 
     if (entryIterator.hasNext()) 
     { 
      var = entryIterator.next().getValue(); 
      ans = var.getCoefficient() * Math.pow(x, var.getPow()); 
     } 

     for (int i = 0; entryIterator.hasNext(); i++) 
     { 
      var = entryIterator.next().getValue(); 
      if (this.operations.get(i))ans *= var.getCoefficient() * Math.pow(x, var.getPow()); 
      else ans += var.getCoefficient() * Math.pow(x, var.getPow()); 
     } 
     return ans; 
    } 

    @Override 
    public String toString() 
    { 
     StringBuilder builder = new StringBuilder(); 
     Iterator<HashMap.Entry<String, Variable>> entryIterator = this.variableHashMap.entrySet().iterator(); 

     if (entryIterator.hasNext())builder.append(entryIterator.next().getValue().toString()); 

     Variable var; 
     for (int i = 0; entryIterator.hasNext(); i++) 
     { 
      var = entryIterator.next().getValue(); 
      if (this.operations.get(i))builder.append("*").append(var.toString()); 
      else builder.append(var.toString()); 
     } 

     return builder.toString(); 
    } 
} 

Main.java

class Main 
{ 
    public static void main(String[] args) 
    { 
     try 
     { 
      long t1 = System.nanoTime(); 

      Variable variable = new Variable("x"); 
      Variable variable1 = new Variable("x", -2.0, 1.0); 
      Variable variable2 = new Variable("x", 3.0, 4.0); 

      Equation equation = new Equation(variable); 
      equation.addVariable(variable1, true);//2x+x 
      equation.addVariable(variable2, true); 

      for (int i = 0; i < 1000000; i++)equation.solveFor(i);//Calculate Million Data Points 
      long t2 = System.nanoTime(); 

      System.out.println((t2-t1)/1000/1000); 
      System.out.println(equation.toString()); 
     } 
     catch (Exception e) 
     { 
      System.out.println("Error: " + e.getMessage()); 
     } 
    } 
} 

Собираюсь ли я в правильном направлении? Есть ли общепринятый Алгоритм для этой проблемы?

Моя основная цель - эффективность, чистота кода и ремонтопригодность кода.

Примечание: Я не являюсь носителем английского языка, поэтому, пожалуйста, игнорируйте любую грамматическую ошибку.

Спасибо.

ответ

0

Я не вижу проблем с вашим первым кодом. Да, может быть, на каждом шаге ваш код «повторяется как tokenzing, проверка, преобразование в RPN, подготовка стеков и очередей и окончательный расчет результата», но в конце все это всего лишь линейное число шагов. Поэтому я не вижу, как это может сделать его очень медленным.

Один из самых больших экранов, которые я видел, был 2560x1440 пикселей, а это означает, что большую часть времени вам понадобится менее 2500 точек, чтобы нарисовать свой график там.

Если вы указываете это код чистоты и код ремонтопригодность, то, скорее всего, код, состоящий из 5 строк лучше, чем код, состоящий из 200

+0

Я хочу, чтобы вычислить миллионы точек. –