the following abstract class which allows us to define speci
the following abstract class, which allows us to define specific mathematical functions as subclasses:
public abstract class AbstractFunction {
// holds arguments that are also functions
private AbstractFunction[] func_args;
// constructor
public AbstractFunction(AbstractFunction[] args) {
this.func_args = args;
}
public AbstractFunction[] getArgs() {
return func_args;
}
public void setArgs(AbstractFunction[] args) {
this.func_args = args;
}
// don\'t know how to implement this for arbitrary functions
public abstract double eval(double x) throws IllegalArgumentException;
}
Notice that this class contains an abstract method eval that takes a number as its input and returns the function’s output. We wish to create concrete subclasses of AbstractFunction which represent actual mathematical function. For example, we can create a subclass SqrtFunction as follows for implementing a square root function.
public class SqrtFunction extends AbstractFunction {
public SqrtFunction() {
super(null);
}
// concrete implementation of eval for computing square root
@Override public double eval(double x) throws IllegalArgumentException {
if (x < 0) throw new IllegalArgumentException(\"Can\'t take square root
of negative number.\");
return Math.sqrt(x);
}
// string representation of the square root function
@Override public String toString() {
String output = \"sqrt(x)\";
return output;
}
}
This allows us to use this object as follows:
AbstractFunction f = new SqrtFunction();
System.out.println(f);
System.out.println(f.eval(16));
which should produce the following output
sqrt(x)
4
Another possible subclass of AbstractFunction would be SumFunction, which represents the sum of two or more functions. Here, the func_args field of AbstractFunction is needed to store the functions that will be summed.
public class SumFunction extends AbstractFunction {
double c; // in case we want to add a constant
// constructor used for two arguments
public SumFunction(AbstractFunction f1, AbstractFunction f2) {
super(null);
AbstractFunction[] args = new AbstractFunction[2];
args[0] = f1;
args[1] = f2;
this.setArgs(args);
c = 0;
}
// constructor used to form \'plus a constant\' function, e.g. f(x)=g(x)+2
public SumFunction(AbstractFunction f, double c) {
super(null);
AbstractFunction[] args = new AbstractFunction[1];
args[0] = f;
this.setArgs(args);
this.c = c;
}
// same constant as before, except the constant comes first
public SumFunction(double c, AbstractFunction f) {
super(null);
AbstractFunction[] args = new AbstractFunction[1];
args[0] = f;
this.setArgs(args);
this.c = c;
}
// constructor used for summing many functions
public SumFunction(AbstractFunction[] args) {
super(args);
c = 0;
}
// continued…
// implement eval (notice the recursive call of eval on other functions)
@Override public double eval(double x) throws IllegalArgumentException {
AbstractFunction[] args = this.getArgs();
int Narg = args.length;
if (Narg == 0 || (Narg == 1 && c == 0))
throw new IllegalArgumentException(\"You must add at least two
functions/numbers.\");
double sum = 0;
for (AbstractFunction f : args) {
sum += f.eval(x);
}
sum += c;
return sum;
}
@Override public String toString() {
AbstractFunction[] args = this.getArgs();
int Narg = args.length;
String output = \"\";
for (int k = 0; k < Narg-1; k++) {
output += args[k].toString() + \" + \";
}
output += args[Narg-1];
if (c != 0) {
output += \" + \" + c;
}
return output;
}
}
Now suppose you wrote the following code:
AbstractFunction f = new SqrtFunction();
AbstractFunction g = new SqrtFunction();
AbstractFunction sum = new SumFunction(f,g);
System.out.println(sum);
System.out.println(sum.eval(9));
The output should be:
sqrt(x) + sqrt(x)
6
Observe how the functions that we can implement using AbstractFunction loosely follow a composite pattern. Now based on this design and examples, I would like you to do the following.
Q. Write a main function that implements the following functions using AbstractFunction objects.
a. f(x) = sin(log(x)) + x2
b. g(x) = sqrt(sin(x))
c. h(x) = log(x)^2 + 3
For each function, print out a string representation of the function and then generate a table of values showing the output for values of x from -10 to 10 in steps of 0.5, i.e., x = -10, -9.5, -9, -8.5, , 9.5, 10. Note that some of the functions will throw an IllegalArgumentException for certain values of x. Your loop should catch these exceptions and print out the string “ERR” for each illegal input. For example, if f(x) was sqrt(x), the output should be:
sqrt(x)
sqrt(-10) = ERR
sqrt(-9.5) = ERR
sqrt(-9.0) = ERR
…
sqrt(-0.5) = ERR
sqrt(0.0) = 0
sqrt(0.5) = 0.7071
sqrt(1) = 1
sqrt(1.5) = 1.2247
…
sqrt(10) = 3.1623
Solution
AbstractFunction.java
public abstract class AbstractFunction
{
// holds arguments that are also functions
private AbstractFunction[] func_args;
// constructor
public AbstractFunction(AbstractFunction[] args) {
this.func_args = args;
}
public AbstractFunction[] getArgs() {
return func_args;
}
public void setArgs(AbstractFunction[] args) {
this.func_args = args;
}
// don\'t know how to implement this for arbitrary functions
public abstract double eval(double x) throws IllegalArgumentException;
}
______________________________
SineFunction.java
public class SineFunction extends AbstractFunction {
public SineFunction() {
super(null);
}
@Override
public double eval(double x) throws IllegalArgumentException {
double val=0.0;
if (x < 0) throw new IllegalArgumentException(\"Can\'t take square root of negative number.\");
val=Math.sin(Math.log(x))+Math.pow(x, 2);
return val;
}
// string representation of the function
@Override public String toString() {
String output = \"sin(log(x)) + x^2\";
return output;
}
}
_____________________________________
SqrtFunction.java
public class SqrtFunction extends AbstractFunction {
public SqrtFunction() {
super(null);
}
// concrete implementation of eval for computing square root
@Override public double eval(double x) throws IllegalArgumentException {
if (x < 0) throw new IllegalArgumentException(\"Can\'t take square root of negative number.\");
return Math.sqrt(Math.sin(x));
}
// string representation of the square root function
@Override public String toString() {
String output = \"sqrt(sin(x))\";
return output;
}
}
_____________________________________
LogFunction.java
public class LogFunction extends AbstractFunction {
public LogFunction() {
super(null);
}
@Override
public double eval(double x) throws IllegalArgumentException {
if (x < 0) throw new IllegalArgumentException(\"Can\'t take square root of negative number.\");
return Math.pow(Math.log(x), 2)+3;
}
// string representation of the square root function
@Override public String toString() {
String output = \"log(x)\";
return output;
}
}
_____________________________________
DriverClass.java
import java.util.Scanner;
public class DriverClass {
public static void main(String[] args) {
double number;
AbstractFunction sf=new SineFunction();
for(double i=-10;i<=10;i=i+0.5)
{
System.out.print(\"sin(log(\"+i+\")) + \"+i+\"^2 =\");
try
{
System.out.printf(\"%.4f\ \",sf.eval(i));
}
catch(Exception e)
{
System.out.println(\"ERR\");
}
}
System.out.println(\"______________________\");
AbstractFunction sqrt=new SqrtFunction();
for(double i=-10;i<=10;i=i+0.5)
{
System.out.print(\"sqrt(sin(\"+i+\")) =\");
try
{
System.out.printf(\"%.4f\ \",sqrt.eval(i));
}
catch(Exception e)
{
System.out.println(\"ERR\");
}
}
System.out.println(\"______________________\");
AbstractFunction logfn=new LogFunction();
for(double i=-10;i<=10;i=i+0.5)
{
System.out.print(\"log(\"+i+\")^2 + 3 =\");
try
{
System.out.printf(\"%.4f\ \",logfn.eval(i));
}
catch(Exception e)
{
System.out.println(\"ERR\");
}
}
}
}
____________________________________
output:
sin(log(-10.0)) + -10.0^2 =ERR
sin(log(-9.5)) + -9.5^2 =ERR
sin(log(-9.0)) + -9.0^2 =ERR
sin(log(-8.5)) + -8.5^2 =ERR
sin(log(-8.0)) + -8.0^2 =ERR
sin(log(-7.5)) + -7.5^2 =ERR
sin(log(-7.0)) + -7.0^2 =ERR
sin(log(-6.5)) + -6.5^2 =ERR
sin(log(-6.0)) + -6.0^2 =ERR
sin(log(-5.5)) + -5.5^2 =ERR
sin(log(-5.0)) + -5.0^2 =ERR
sin(log(-4.5)) + -4.5^2 =ERR
sin(log(-4.0)) + -4.0^2 =ERR
sin(log(-3.5)) + -3.5^2 =ERR
sin(log(-3.0)) + -3.0^2 =ERR
sin(log(-2.5)) + -2.5^2 =ERR
sin(log(-2.0)) + -2.0^2 =ERR
sin(log(-1.5)) + -1.5^2 =ERR
sin(log(-1.0)) + -1.0^2 =ERR
sin(log(-0.5)) + -0.5^2 =ERR
sin(log(0.0)) + 0.0^2 =NaN
sin(log(0.5)) + 0.5^2 =-0.3890
sin(log(1.0)) + 1.0^2 =1.0000
sin(log(1.5)) + 1.5^2 =2.6444
sin(log(2.0)) + 2.0^2 =4.6390
sin(log(2.5)) + 2.5^2 =7.0433
sin(log(3.0)) + 3.0^2 =9.8906
sin(log(3.5)) + 3.5^2 =13.1999
sin(log(4.0)) + 4.0^2 =16.9830
sin(log(4.5)) + 4.5^2 =21.2478
sin(log(5.0)) + 5.0^2 =25.9993
sin(log(5.5)) + 5.5^2 =31.2410
sin(log(6.0)) + 6.0^2 =36.9757
sin(log(6.5)) + 6.5^2 =43.2050
sin(log(7.0)) + 7.0^2 =49.9305
sin(log(7.5)) + 7.5^2 =57.1530
sin(log(8.0)) + 8.0^2 =64.8734
sin(log(8.5)) + 8.5^2 =73.0923
sin(log(9.0)) + 9.0^2 =81.8101
sin(log(9.5)) + 9.5^2 =91.0273
sin(log(10.0)) + 10.0^2 =100.7440
______________________
sqrt(sin(-10.0)) =ERR
sqrt(sin(-9.5)) =ERR
sqrt(sin(-9.0)) =ERR
sqrt(sin(-8.5)) =ERR
sqrt(sin(-8.0)) =ERR
sqrt(sin(-7.5)) =ERR
sqrt(sin(-7.0)) =ERR
sqrt(sin(-6.5)) =ERR
sqrt(sin(-6.0)) =ERR
sqrt(sin(-5.5)) =ERR
sqrt(sin(-5.0)) =ERR
sqrt(sin(-4.5)) =ERR
sqrt(sin(-4.0)) =ERR
sqrt(sin(-3.5)) =ERR
sqrt(sin(-3.0)) =ERR
sqrt(sin(-2.5)) =ERR
sqrt(sin(-2.0)) =ERR
sqrt(sin(-1.5)) =ERR
sqrt(sin(-1.0)) =ERR
sqrt(sin(-0.5)) =ERR
sqrt(sin(0.0)) =0.0000
sqrt(sin(0.5)) =0.6924
sqrt(sin(1.0)) =0.9173
sqrt(sin(1.5)) =0.9987
sqrt(sin(2.0)) =0.9536
sqrt(sin(2.5)) =0.7736
sqrt(sin(3.0)) =0.3757
sqrt(sin(3.5)) =NaN
sqrt(sin(4.0)) =NaN
sqrt(sin(4.5)) =NaN
sqrt(sin(5.0)) =NaN
sqrt(sin(5.5)) =NaN
sqrt(sin(6.0)) =NaN
sqrt(sin(6.5)) =0.4638
sqrt(sin(7.0)) =0.8105
sqrt(sin(7.5)) =0.9685
sqrt(sin(8.0)) =0.9947
sqrt(sin(8.5)) =0.8936
sqrt(sin(9.0)) =0.6420
sqrt(sin(9.5)) =NaN
sqrt(sin(10.0)) =NaN
______________________
log(-10.0)^2 + 3 =ERR
log(-9.5)^2 + 3 =ERR
log(-9.0)^2 + 3 =ERR
log(-8.5)^2 + 3 =ERR
log(-8.0)^2 + 3 =ERR
log(-7.5)^2 + 3 =ERR
log(-7.0)^2 + 3 =ERR
log(-6.5)^2 + 3 =ERR
log(-6.0)^2 + 3 =ERR
log(-5.5)^2 + 3 =ERR
log(-5.0)^2 + 3 =ERR
log(-4.5)^2 + 3 =ERR
log(-4.0)^2 + 3 =ERR
log(-3.5)^2 + 3 =ERR
log(-3.0)^2 + 3 =ERR
log(-2.5)^2 + 3 =ERR
log(-2.0)^2 + 3 =ERR
log(-1.5)^2 + 3 =ERR
log(-1.0)^2 + 3 =ERR
log(-0.5)^2 + 3 =ERR
log(0.0)^2 + 3 =Infinity
log(0.5)^2 + 3 =3.4805
log(1.0)^2 + 3 =3.0000
log(1.5)^2 + 3 =3.1644
log(2.0)^2 + 3 =3.4805
log(2.5)^2 + 3 =3.8396
log(3.0)^2 + 3 =4.2069
log(3.5)^2 + 3 =4.5694
log(4.0)^2 + 3 =4.9218
log(4.5)^2 + 3 =5.2622
log(5.0)^2 + 3 =5.5903
log(5.5)^2 + 3 =5.9062
log(6.0)^2 + 3 =6.2104
log(6.5)^2 + 3 =6.5036
log(7.0)^2 + 3 =6.7866
log(7.5)^2 + 3 =7.0598
log(8.0)^2 + 3 =7.3241
log(8.5)^2 + 3 =7.5799
log(9.0)^2 + 3 =7.8278
log(9.5)^2 + 3 =8.0683
log(10.0)^2 + 3 =8.3019
____________________Thank You









