如何将字符串转换为代数表达式
How to turn a String into a Algebraic Expression
所以我正在尝试编写一个程序来获取像 3x^2 + x + 8 这样的函数,然后绘制该函数的图形。我正在使用 eval() 方法将 String 转换为表达式,但它一直抛出 NullPointerException。
package Function;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.JFrame;
public class FunctionGrapherTest
{
public static void main(String[] args)
{
JFrame frame = new JFrame();
FunctionGrapherComponent comp = new FunctionGrapherComponent();
frame.setSize(600, 600);
frame.setTitle("Function");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.add(comp);
frame.getContentPane().add(comp.control(), BorderLayout.SOUTH);
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
int x = (int)((dimension.getWidth() - frame.getWidth()) / 2);
int y = (int)((dimension.getHeight() - frame.getHeight()) / 2);
frame.setLocation(x, y);
}
}
package Function;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
public class FunctionGrapherComponent extends JPanel
{
private static final long serialVersionUID = 1L;
public FunctionGrapherComponent()
{
JPanel field = new JPanel();
JLabel y = new JLabel("y = ", SwingConstants.RIGHT);
field.add(y);
equaField = new JTextField(15);
field.add(equaField);
control = new JPanel();
control.setLayout(new GridLayout(1, 3));
control.add(field);
JButton draw = makeButton("Graph");
control.add(draw);
count = 0;
}
public JPanel control()
{
return control;
}
public JButton makeButton(String label)
{
JButton button = new JButton(label);
class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
String equation = equaField.getText();
if(!equation.equals("") || equation != null)
{
equa = equation;
count = 1;
repaint();
}
equaField.setText("");
}
}
ActionListener listener = new ButtonListener();
button.addActionListener(listener);
return button;
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
Axes axes = new Axes(xPixel(XMIN), xPixel(XMAX), yPixel(YMIN), yPixel(YMAX),
xPixel(0), yPixel(0), sWidth(1), sHeight(1));
axes.drawAxes(g2);
axes.drawTicks(g2);
if(count == 1)
{
Function func = new Function();
delta = (XMAX - XMIN) / 100;
for(double i = XMIN; i <= (XMAX - delta); i = i + delta)
{
x1 = xPixel(i);
y1 = yPixel(func.functionVal(i, equa));
x2 = xPixel(i + delta);
y2 = yPixel(func.functionVal(i + delta, equa));
func.plot(g2, x1, y1, x2, y2);
}
count = 0;
}
}
public double xPixel(double xuser)
{
return (xuser - XMIN) * (getWidth( ) - 1) / (XMAX - XMIN);
}
public double yPixel(double yuser)
{
return (yuser - YMAX) * (getHeight( ) - 1) / (YMIN - YMAX);
}
public double sHeight(double yuser)
{
return yuser * (getHeight() - 1) / (YMAX - YMIN);
}
public double sWidth(double xuser)
{
return xuser * (getWidth() - 1) / (XMAX - XMIN);
}
private static final double XMIN = -100;
private static final double XMAX = 100;
private static final double YMIN = -100;
private static final double YMAX = 100;
private double delta;
private double x1;
private double y1;
private double x2;
private double y2;
private int count;
private JPanel control;
private JTextField equaField;
private String equa;
}
package Function;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class Function
{
public Function()
{
}
public void plot(Graphics2D g2, double x1, double y1, double x2, double y2)
{
Line2D.Double seg = new Line2D.Double(x1, y1, x2, y2);
g2.draw(seg);
}
public double functionVal(double x, String equa)
{
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("Java");
try
{
funcVal = (double)engine.eval(equa);
}
catch (ScriptException e)
{}
return funcVal;
}
private double funcVal;
}
package Function;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
public class Axes
{
public Axes(double xmin, double xmax, double ymin, double ymax,
double xzero, double yzero, double xunit, double yunit)
{
xMin = xmin;
xMax = xmax;
yMin = ymin;
yMax = ymax;
xZero = xzero;
yZero = yzero;
xUnit = xunit;
yUnit = yunit;
}
public void drawAxes(Graphics2D g2)
{
Line2D.Double xAxis = new Line2D.Double(xMin, yZero, xMax, yZero);
Line2D.Double yAxis = new Line2D.Double(xZero, yMin, xZero, yMax);
g2.draw(xAxis);
g2.draw(yAxis);
}
public void drawTicks(Graphics2D g2)
{
for(double i = xZero + xUnit; i <= xMax; i = i + xUnit)
{
Line2D.Double tick = new Line2D.Double(i, yZero + TICK_LENGTH, i, yZero - TICK_LENGTH);
g2.draw(tick);
}
for(double i = xZero - xUnit; i >= xMin; i = i - xUnit)
{
Line2D.Double tick = new Line2D.Double(i, yZero + TICK_LENGTH, i, yZero - TICK_LENGTH);
g2.draw(tick);
}
for(double i = yZero + yUnit; i <= yMin; i = i + yUnit)
{
Line2D.Double tick = new Line2D.Double(xZero + TICK_LENGTH, i, xZero - TICK_LENGTH, i);
g2.draw(tick);
}
for(double i = yZero - yUnit; i >= yMax; i = i - yUnit)
{
Line2D.Double tick = new Line2D.Double(xZero + TICK_LENGTH, i, xZero - TICK_LENGTH, i);
g2.draw(tick);
}
}
private double xMin;
private double xMax;
private double yMin;
private double yMax;
private double xZero;
private double yZero;
private double xUnit;
private double yUnit;
private static final double TICK_LENGTH = 3;
}
首先将 ScriptEngine engine = mgr.getEngineByName("Java");
更改为 ScriptEngine engine = mgr.getEngineByName("javascript");
,尽管有些人认为 Java 不是脚本语言,Java 和 Java脚本
此外,您不应该忽略 engine
...
抛出的异常
try {
System.out.println(equa);
funcVal = ((Number) engine.eval(equa)).doubleValue();
} catch (ScriptException e) {
e.printStackTrace();
}
如果您不在每次调用 functionVal
时重新创建 ScriptEngine
,您也会发现它更快
public static class Function {
private final ScriptEngine engine;
public Function() {
ScriptEngineManager mgr = new ScriptEngineManager();
engine = mgr.getEngineByName("javascript");
}
public void plot(Graphics2D g2, double x1, double y1, double x2, double y2) {
Line2D.Double seg = new Line2D.Double(x1, y1, x2, y2);
g2.draw(seg);
}
public double functionVal(double x, String equa) {
try {
System.out.println(equa);
funcVal = ((Number) engine.eval(equa)).doubleValue();
} catch (ScriptException e) {
}
return funcVal;
}
private double funcVal;
}
已更新
所以,假设你想解方程 3x^2 + x + 8
,你需要给 x
一些值...
engine.put("x", 10);
然后你可以使用 3*2^+x+8
作为你的等式...
funcVal = ((Number) engine.eval("3*2^+x+8")).doubleValue();
例如...
public double functionVal(double x, String equa) {
try {
System.out.println(equa);
engine.put("x", 10);
funcVal = ((Number) engine.eval(equa)).doubleValue();
System.out.println(equa + " = " + funcVal);
} catch (ScriptException e) {
e.printStackTrace();
}
return funcVal;
}
所以我正在尝试编写一个程序来获取像 3x^2 + x + 8 这样的函数,然后绘制该函数的图形。我正在使用 eval() 方法将 String 转换为表达式,但它一直抛出 NullPointerException。
package Function;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.JFrame;
public class FunctionGrapherTest
{
public static void main(String[] args)
{
JFrame frame = new JFrame();
FunctionGrapherComponent comp = new FunctionGrapherComponent();
frame.setSize(600, 600);
frame.setTitle("Function");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.add(comp);
frame.getContentPane().add(comp.control(), BorderLayout.SOUTH);
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
int x = (int)((dimension.getWidth() - frame.getWidth()) / 2);
int y = (int)((dimension.getHeight() - frame.getHeight()) / 2);
frame.setLocation(x, y);
}
}
package Function;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
public class FunctionGrapherComponent extends JPanel
{
private static final long serialVersionUID = 1L;
public FunctionGrapherComponent()
{
JPanel field = new JPanel();
JLabel y = new JLabel("y = ", SwingConstants.RIGHT);
field.add(y);
equaField = new JTextField(15);
field.add(equaField);
control = new JPanel();
control.setLayout(new GridLayout(1, 3));
control.add(field);
JButton draw = makeButton("Graph");
control.add(draw);
count = 0;
}
public JPanel control()
{
return control;
}
public JButton makeButton(String label)
{
JButton button = new JButton(label);
class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
String equation = equaField.getText();
if(!equation.equals("") || equation != null)
{
equa = equation;
count = 1;
repaint();
}
equaField.setText("");
}
}
ActionListener listener = new ButtonListener();
button.addActionListener(listener);
return button;
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
Axes axes = new Axes(xPixel(XMIN), xPixel(XMAX), yPixel(YMIN), yPixel(YMAX),
xPixel(0), yPixel(0), sWidth(1), sHeight(1));
axes.drawAxes(g2);
axes.drawTicks(g2);
if(count == 1)
{
Function func = new Function();
delta = (XMAX - XMIN) / 100;
for(double i = XMIN; i <= (XMAX - delta); i = i + delta)
{
x1 = xPixel(i);
y1 = yPixel(func.functionVal(i, equa));
x2 = xPixel(i + delta);
y2 = yPixel(func.functionVal(i + delta, equa));
func.plot(g2, x1, y1, x2, y2);
}
count = 0;
}
}
public double xPixel(double xuser)
{
return (xuser - XMIN) * (getWidth( ) - 1) / (XMAX - XMIN);
}
public double yPixel(double yuser)
{
return (yuser - YMAX) * (getHeight( ) - 1) / (YMIN - YMAX);
}
public double sHeight(double yuser)
{
return yuser * (getHeight() - 1) / (YMAX - YMIN);
}
public double sWidth(double xuser)
{
return xuser * (getWidth() - 1) / (XMAX - XMIN);
}
private static final double XMIN = -100;
private static final double XMAX = 100;
private static final double YMIN = -100;
private static final double YMAX = 100;
private double delta;
private double x1;
private double y1;
private double x2;
private double y2;
private int count;
private JPanel control;
private JTextField equaField;
private String equa;
}
package Function;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class Function
{
public Function()
{
}
public void plot(Graphics2D g2, double x1, double y1, double x2, double y2)
{
Line2D.Double seg = new Line2D.Double(x1, y1, x2, y2);
g2.draw(seg);
}
public double functionVal(double x, String equa)
{
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("Java");
try
{
funcVal = (double)engine.eval(equa);
}
catch (ScriptException e)
{}
return funcVal;
}
private double funcVal;
}
package Function;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
public class Axes
{
public Axes(double xmin, double xmax, double ymin, double ymax,
double xzero, double yzero, double xunit, double yunit)
{
xMin = xmin;
xMax = xmax;
yMin = ymin;
yMax = ymax;
xZero = xzero;
yZero = yzero;
xUnit = xunit;
yUnit = yunit;
}
public void drawAxes(Graphics2D g2)
{
Line2D.Double xAxis = new Line2D.Double(xMin, yZero, xMax, yZero);
Line2D.Double yAxis = new Line2D.Double(xZero, yMin, xZero, yMax);
g2.draw(xAxis);
g2.draw(yAxis);
}
public void drawTicks(Graphics2D g2)
{
for(double i = xZero + xUnit; i <= xMax; i = i + xUnit)
{
Line2D.Double tick = new Line2D.Double(i, yZero + TICK_LENGTH, i, yZero - TICK_LENGTH);
g2.draw(tick);
}
for(double i = xZero - xUnit; i >= xMin; i = i - xUnit)
{
Line2D.Double tick = new Line2D.Double(i, yZero + TICK_LENGTH, i, yZero - TICK_LENGTH);
g2.draw(tick);
}
for(double i = yZero + yUnit; i <= yMin; i = i + yUnit)
{
Line2D.Double tick = new Line2D.Double(xZero + TICK_LENGTH, i, xZero - TICK_LENGTH, i);
g2.draw(tick);
}
for(double i = yZero - yUnit; i >= yMax; i = i - yUnit)
{
Line2D.Double tick = new Line2D.Double(xZero + TICK_LENGTH, i, xZero - TICK_LENGTH, i);
g2.draw(tick);
}
}
private double xMin;
private double xMax;
private double yMin;
private double yMax;
private double xZero;
private double yZero;
private double xUnit;
private double yUnit;
private static final double TICK_LENGTH = 3;
}
首先将 ScriptEngine engine = mgr.getEngineByName("Java");
更改为 ScriptEngine engine = mgr.getEngineByName("javascript");
,尽管有些人认为 Java 不是脚本语言,Java 和 Java脚本
此外,您不应该忽略 engine
...
try {
System.out.println(equa);
funcVal = ((Number) engine.eval(equa)).doubleValue();
} catch (ScriptException e) {
e.printStackTrace();
}
如果您不在每次调用 functionVal
ScriptEngine
,您也会发现它更快
public static class Function {
private final ScriptEngine engine;
public Function() {
ScriptEngineManager mgr = new ScriptEngineManager();
engine = mgr.getEngineByName("javascript");
}
public void plot(Graphics2D g2, double x1, double y1, double x2, double y2) {
Line2D.Double seg = new Line2D.Double(x1, y1, x2, y2);
g2.draw(seg);
}
public double functionVal(double x, String equa) {
try {
System.out.println(equa);
funcVal = ((Number) engine.eval(equa)).doubleValue();
} catch (ScriptException e) {
}
return funcVal;
}
private double funcVal;
}
已更新
所以,假设你想解方程 3x^2 + x + 8
,你需要给 x
一些值...
engine.put("x", 10);
然后你可以使用 3*2^+x+8
作为你的等式...
funcVal = ((Number) engine.eval("3*2^+x+8")).doubleValue();
例如...
public double functionVal(double x, String equa) {
try {
System.out.println(equa);
engine.put("x", 10);
funcVal = ((Number) engine.eval(equa)).doubleValue();
System.out.println(equa + " = " + funcVal);
} catch (ScriptException e) {
e.printStackTrace();
}
return funcVal;
}