// Improved Euler's Method, coded by David Protas, c.2002 // Any corrections or suggestions for improvement of this code will be // appreciated and should be sent to david.protas@csun.edu // Latest revision: November 12, 2003 /********************* * Document: IEM.java *********************/ import java.applet.*; import java.awt.*; import expr.*; public class IEM extends Applet { final int MaxN = 100; //Maximum number of subintervals double x_0D, y_0D, bD, ymin, ymax, h, a, b, plm; int nI, counter = -1, last; double[] xArray = new double[MaxN+1]; double[] pyArray = new double[MaxN+1]; double[] yArray = new double[MaxN+1]; double[] prmArray = new double[MaxN+1]; boolean predict = false; Panel top, pan1, pan2, pan3, bottom, pan4, pan5; Label functionLabel, inputLabelX ,inputLabelY, inputLabelB, inputLabelN, message; TextField functionField, inputFieldX, inputFieldY, inputFieldB, inputFieldN; TextArea results; Button enter, approx; IEM_G graph; Color babyBlue; public void init() { setLayout(new BorderLayout(4,0)); top = new Panel(); top.setLayout(new GridLayout(3,1)); bottom = new Panel(); bottom.setLayout(new GridLayout(3,1)); pan1 = new Panel(); pan2 = new Panel(); pan3 = new Panel(); pan4 = new Panel(); pan5 = new Panel(); functionLabel = new Label("f(x,y) = "); functionField = new TextField(20); inputLabelX = new Label(" x_0 ="); inputLabelY = new Label(" y_0 ="); inputLabelB = new Label(" b ="); inputLabelN = new Label(" n ="); inputFieldX = new TextField(5); inputFieldY = new TextField(5); inputFieldB = new TextField(5); inputFieldN = new TextField(5); enter = new Button("Enter"); approx = new Button("Approximate"); results = new TextArea(" x_n y_n ", 10, 30); results.setEditable(false); message = new Label(" " + " "); graph = new IEM_G(); babyBlue = new Color(204,255,255); pan1.add(functionLabel); pan1.add(functionField); top.add(pan1); pan2.add(inputLabelX); pan2.add(inputFieldX); pan2.add(inputLabelY); pan2.add(inputFieldY); top.add(pan2); pan3.add(inputLabelB); pan3.add(inputFieldB); pan3.add(inputLabelN); pan3.add(inputFieldN); pan3.add(enter); pan3.add(approx); top.add(pan3); add("North",top); add("Center",graph); add("East",results); pan5.add(message); bottom.add(pan5); add("South",bottom); setBackground(babyBlue); pan1.setBackground(babyBlue); pan2.setBackground(babyBlue); pan3.setBackground(babyBlue); pan4.setBackground(babyBlue); pan5.setBackground(babyBlue); message.setForeground(Color.red); message.setBackground(babyBlue); results.setFont(new Font("Courier",Font.PLAIN,10)); } public boolean action(Event evt, Object arg) { Variable x = null; Variable y = null; Expr function = null, inputX = null, inputY = null, inputB = null; if (evt.target == enter) { counter = 0; graph.counter = counter; message.setText(""); try { x = Variable.make ("x"); y = Variable.make ("y"); function = Parser.parse (functionField.getText()); inputX = Parser.parse(inputFieldX.getText()); inputY = Parser.parse(inputFieldY.getText()); inputB = Parser.parse(inputFieldB.getText()); } catch (Syntax_error e) { message.setText("" + e); } Variable.make ("pi").set_value (Math.PI); Variable.make ("e").set_value (Math.E); x_0D = inputX.value(); y_0D = inputY.value(); bD = inputB.value(); if (entryValid(inputFieldN.getText()) == false) message.setText("n needs to be an integer. Try again."); else { nI = intFromString(inputFieldN.getText()); last = nI; if((nI < 1) || (nI > MaxN)) message.setText("Applet requires n to be a positive integer <= " + MaxN); else if (x_0D < bD) { h = (bD - x_0D)/nI; graph.nI = nI; if (nI > 10) approx.setLabel("Run"); else approx.setLabel("Predict"); results.setText(" x_n y_n " + "\n" + rndOff(x_0D) + " " + rndOff(y_0D)); graph.x_0D = x_0D; graph.y_0D = y_0D; graph.bD = bD; xArray[0] = x_0D; yArray[0] = y_0D; pyArray[0] = y_0D; graph.xArray[0] = xArray[0]; graph.yArray[0] = yArray[0]; ymin = Math.min(y_0D,-.5); ymax = Math.max(y_0D,.2); for (int i = 1; i <= nI; i++) { x.set_value(xArray[i-1]); y.set_value(yArray[i-1]); plm = function.value(); if (plm != plm) { //tests whether plm is a number message.setText("Singularity encountered. Computation ends at x = " + rndOff(xArray[i-1]).trim() + "."); last = i-1; break; } pyArray[i] = yArray[i-1] + h*plm; //Array of predicted y values if (pyArray[i] < ymin) ymin = pyArray[i]; //finding min value of y if (pyArray[i] > ymax) ymax = pyArray[i]; //finding max value of y xArray[i] = x_0D + i*h; //Array of x values graph.xArray[i] =xArray[i]; x.set_value(xArray[i]); y.set_value(pyArray[i]); prmArray[i-1] = function.value(); if (prmArray[i-1] != prmArray[i-1]) { //tests whether prmArray[i-1] is a number message.setText("Singularity encountered. Computation ends at x = " + rndOff(xArray[i-1]).trim() + "."); last = i-1; break; } yArray[i] = yArray[i-1] + h*(plm + prmArray[i-1])/2; //Array of y values graph.yArray[i] = yArray[i]; if (yArray[i] < ymin) ymin = yArray[i]; //finding min value of y if (yArray[i] > ymax) ymax = yArray[i]; //finding max value of y } graph.ymin = ymin; graph.ymax = ymax; graph.repaint(); predict = true; graph.predict = predict; counter = 1; } //end of else if x_0D < bD else message.setText("Need x_0 < b. Try again."); } //end of else entry valid return true; } //end of evt.target == enter if (evt.target == approx) { if (nI > 10) { graph.counter = last; for (int i = 1; i <= last; i++) results.appendText("\n" + rndOff(xArray[i]) + " " + rndOff(yArray[i])); graph.repaint(); } else { graph.counter = counter; if (counter <= last) { graph.nI = last; if (predict == false) { results.appendText("\n" + rndOff(xArray[counter]) + " " + rndOff(yArray[counter])); graph.counter = counter; approx.setLabel("Predict"); counter = counter + 1; } else approx.setLabel("Correct"); graph.predict = predict; if (counter <= last) { graph.py = pyArray[counter]; graph.dir = prmArray[counter-1]; } graph.repaint(); if (predict == false) predict = true; else predict = false; } } return true; } //end of evt.target == approx return false; } //end of action public static int intFromString(String str) { Integer intObj = new Integer(str); return intObj.intValue(); } private boolean entryValid(String entry) { boolean status; try { double number = intFromString(entry); status = true; } catch(NumberFormatException e) { status =false; } return status; } public static String rndOff(double number) //to 5 places past the decimal { String strnum, bigstrnum, substrnum = " 0.00000"; int period, lngth; long longnum; if ((number >= 0.001) || (number <= -0.001) || (number != number)) { number = Math.pow(0.1,5)*Math.round(Math.pow(10,5)*number); strnum = String.valueOf(number); bigstrnum = " " + strnum + " "; period = bigstrnum.indexOf('.'); substrnum = bigstrnum.substring(period -6, period + 6); if ((number >= 1000000) || (number <= -100000) || (number != number)) substrnum = "big magnitude"; } else { longnum = Math.round(Math.pow(10,5)*number); if (longnum == 0) substrnum = " 0.00000"; else { strnum = String.valueOf(longnum); if (longnum < 0) strnum = strnum.substring(1); lngth = strnum.length(); switch (lngth) { case 1: substrnum = " 0.0000" + strnum; break; case 2: substrnum = " 0.000" + strnum; break; default: substrnum = " error"; } if (longnum < 0) substrnum = " -" + substrnum.substring(5); } } return substrnum; } } //end of IEM