// Simpson's Rule, 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: January 8, 2003 /********************* * Document: Sim.java *********************/ import java.applet.*; import java.awt.*; import expr.*; public class SiM extends Applet { final int K = 400; // Number of points used to draw graph final int MaxN = 100; //Maximum number of subintervals double aD, bD, ymin, ymax, h, sum, a, b, c; int nI, Kp, firstj; double[] xarray = new double[K+1]; double[] yarray = new double[K+1]; double[] xArray = new double[MaxN+1]; double[] yArray = new double[MaxN+1]; double[] tarray = new double[K+1]; Panel top, pan1, pan2, pan3, bottom, pan4, pan5, pan6; Label functionLabel,inputLabelA, inputLabelB, inputLabelN, answer, message; TextField functionField, inputFieldA, inputFieldB, inputFieldN; Button plot, approx; GrCanvas 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(); pan6 = new Panel(); functionLabel = new Label("f(x) = "); functionField = new TextField(20); inputLabelA = new Label(" a = "); inputLabelB = new Label(" b = "); inputLabelN = new Label(" n = "); inputFieldA = new TextField(5); inputFieldB = new TextField(5); inputFieldN = new TextField(5); plot = new Button("Plot"); approx = new Button("Approximate"); answer = new Label(" " + " "); message = new Label(" " + " "); graph = new GrCanvas(); babyBlue = new Color(204,255,255); pan1.add(functionLabel); pan1.add(functionField); top.add(pan1); pan2.add(inputLabelA); pan2.add(inputFieldA); pan2.add(inputLabelB); pan2.add(inputFieldB); top.add(pan2); pan3.add(plot); top.add(pan3); add("North",top); add("Center",graph); pan4.add(inputLabelN); pan4.add(inputFieldN); bottom.add(pan4); pan5.add(approx); pan5.add(answer); bottom.add(pan5); pan6.add(message); bottom.add(pan6); add("South",bottom); setBackground(babyBlue); pan1.setBackground(babyBlue); pan2.setBackground(babyBlue); pan3.setBackground(babyBlue); pan4.setBackground(babyBlue); pan5.setBackground(babyBlue); pan6.setBackground(babyBlue); message.setForeground(Color.red); message.setBackground(babyBlue); answer.setBackground(babyBlue); } public boolean action(Event evt, Object arg) { Variable x = null; Expr function = null, inputA = null, inputB = null; if (evt.target == plot) { answer.setText(""); message.setText(""); try { x = Variable.make ("x"); function = Parser.parse (functionField.getText()); inputA = Parser.parse(inputFieldA.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); aD = inputA.value(); bD = inputB.value(); if (aD < bD) { graph.aD = aD; graph.bD = bD; ymin = -.0000001; ymax = .0000001; for (int i = 0; i <= K; i++) { xarray[i] = aD + i*(bD - aD)/K; //Array of x values x.set_value(xarray[i]); yarray[i] = function.value(); //Array of y values graph.xarray[i] = xarray[i]; graph.yarray[i] = yarray[i]; if (yarray[i] < ymin) ymin = yarray[i]; //find min value of y if (yarray[i] > ymax) ymax = yarray[i]; //find max value of y } graph.ymin = ymin; graph.ymax = ymax; graph.phase = 0; graph.repaint(); } //end of if aD < bD else message.setText("Need a < b. Try again."); return true; } //end of evt.target == plot if (evt.target == approx) { answer.setText(""); try { x = Variable.make ("x"); function = Parser.parse (functionField.getText()); } catch (Syntax_error e) { message.setText("" + e); } graph.phase = 1; if (entryValid(inputFieldN.getText()) == false) message.setText("n needs to be an integer. Try again."); else { nI = intFromString(inputFieldN.getText()); if ((nI < 2) || (nI%2 == 1)) message.setText("n needs to be positive and even. Try again."); else if (nI > MaxN) message.setText("Applet requires n <= " + MaxN + ". Try again."); else { graph.nI = nI; h = (bD - aD)/nI; for (int i = 0; i <= nI; i++) { xArray[i] = aD + i*h; graph.xArray[i] = xArray[i]; x.set_value(xArray[i]); yArray[i] = function.value(); graph.yArray[i] = yArray[i]; } message.setText(""); sum = 0; Kp = 2*K/nI; for (int i = 1; i < nI; i = i + 2) { sum = sum + yArray[i-1] + 4*yArray[i] + yArray[i+1]; a = (yArray[i-1] - 2*yArray[i] + yArray[i+1])/(2*h*h); b = (h*yArray[i+1] - h*yArray[i-1] - 2*xArray[i]*yArray[i+1] - 2*xArray[i]*yArray[i-1] +4*xArray[i]*yArray[i])/(2*h*h); c = (2*h*h*yArray[i] + h*xArray[i]*yArray[i-1] - h*xArray[i]*yArray[i+1] + xArray[i]*xArray[i]*yArray[i-1] + xArray[i]*xArray[i]*yArray[i+1] - 2*xArray[i]*xArray[i]*yArray[i])/(2*h*h); firstj = (i-1)*K/nI; for (int j = 0; j <= Kp; j++) { tarray[firstj+j] = aD + (firstj+j)*(bD - aD)/K; graph.tarray[firstj+j] = tarray[firstj+j]; graph.parray[firstj+j] = a*tarray[firstj+j]*tarray[firstj+j] + b*tarray[firstj+j] + c; } graph.tarray[K] = bD; graph.parray[K] = yarray[K]; } answer.setText("Answer: " + rndOff(sum*h/3)); graph.repaint(); } //end of else nI > MaxN } //end of else entryValid 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 = " NaN"; int period, positionE, lngth; long longnum; if ((number >= 0.001) || (number <= -0.001)) { if ((number < 100000000) && (number > -100000000)) number = Math.pow(0.1,5)*Math.round(Math.pow(10,5)*number); strnum = String.valueOf(number); if (strnum.indexOf('f') > -1) substrnum = strnum; else { bigstrnum = strnum + " "; period = bigstrnum.indexOf('.'); positionE = bigstrnum.indexOf('E'); if (positionE == -1) substrnum = bigstrnum.substring(0, period + 6); else { substrnum = bigstrnum.substring(0, Math.min(period + 6, positionE)) + " * 10^" + bigstrnum.substring(positionE + 1); } } } 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(3); } } return substrnum; } }