How to calculate value of math expression and check user answer? - java

Any help or advice would be greatly appreciated. I'm dooing a simple game which generates ten different, random questions. The questions can be composed from 2, 3 or 4 integers.Something like this: 552 − 4 − 101, 102 / 3 / 3, 589 − 281, 123 + 56 + 2.
The question will be displayed in a textview and then the user can take a guess, entering values into an edittext and then upon clicking a key on a custom keypad, it will check the answer, and then display the next question until it reaches 10 questions. I have a problem with imputing the answer from the code i have. No matter what i do here i cant input the answer to the randomly generated expression.
public enum Operator {
PLUS("+"), MINUS("-"), MULTIPLIER("*"), DIVIDER("/");
private String displayValue;
private Operator(String displayValue) {
this.displayValue = displayValue;
}
public String getDisplayValue() {
return displayValue;
}}
public class Question{
private List<QuestionElement> questionElements;
public Question(int sizeOfQuestionElemets) {
questionElements = new ArrayList<QuestionElement>(sizeOfQuestionElemets);
}
public void addElement(QuestionElement questionElement) {
questionElements.add(questionElement);
}
public List<QuestionElement> getElements() {
return questionElements;
}
public int size() {
return questionElements.size();
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
for (QuestionElement questionElement : questionElements) {
sb.append(questionElement);
}
return sb.toString().trim();
}
}
public class QuestionElement {
private int value;
private Operator operator;
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public Operator getOperator() {
return operator;
}
public void setOperator(Operator operator) {
this.operator = operator;
}
#Override
public String toString() {
return value + (operator == null ? "" : " " + operator.getDisplayValue()) + " ";
}
}
public class RandomQuestions {
static QuestionElement q = new QuestionElement();
private static final int NUMBER_OF_QUESTIONS = 10;
private static final int MIN_QUESTION_ELEMENTS = 2;
private static final int MAX_QUESTION_ELEMENTS = 2;
private static final int MIN_QUESTION_ELEMENT_VALUE = 1;
private static final int MAX_QUESTION_ELEMENT_VALUE = 20;
private final Random randomGenerator = new Random();
public List<Question> getGeneratedRandomQuestions() {
List<Question> randomQuestions = new ArrayList<>(NUMBER_OF_QUESTIONS);
int randomQuestionElementsCapacity = getRandomQuestionElementsCapacity();
Question question = new Question(randomQuestionElementsCapacity);
for (int j = 0; j < randomQuestionElementsCapacity; j++) {
boolean isLastIteration = j + 1 == randomQuestionElementsCapacity;
QuestionElement questionElement = new QuestionElement();
questionElement.setValue(getRandomQuestionElementValue());
questionElement.setOperator(isLastIteration ? null
: Operator.values()[randomGenerator.nextInt(Operator.values().length)]);
question.addElement(questionElement);
}
randomQuestions.add(question);
return randomQuestions;
}
private int getRandomQuestionElementsCapacity() {
return getRandomIntegerFromRange(MIN_QUESTION_ELEMENTS, MAX_QUESTION_ELEMENTS);
}
private int getRandomQuestionElementValue() {
return getRandomIntegerFromRange(MIN_QUESTION_ELEMENT_VALUE, MAX_QUESTION_ELEMENT_VALUE);
}
private int getRandomIntegerFromRange(int min, int max) {
return randomGenerator.nextInt(max - min + 1) + min;
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
RandomQuestions questionGenerator = new RandomQuestions();
List<Question> randomQuestions = questionGenerator.getGeneratedRandomQuestions();
for (Question question : randomQuestions) {
System.out.println(""+ question+"=?");
int answer = input.nextInt();
if (answer == q.getValue()) {
System.out.println("CORRECT");
}else{
System.err.println("STILL NOT WORKING");
}
}
}
}

In your main() you are printing question, reading an answer from the user and then comparing the answer to q.getValue(). q is a question element that is not related to question and always has value 0. So the trick is to answer 0 no matter what the question is, then the program will print CORRECT. :-)
I haven’t found anywhere in your code where you are calculating the correct value of the math expression. This would probably be a good first step towards checking whether the user has indeed entered the correct result.
Calculating the correct result is not really trivial if we insist on taking operator precedence into account. 4 + 3 * 2 should be 10 (not 14). I believe that reading about the Shunting-yard algorithm should get you some of the way. It’s an algorithm for parsing a math expression, which is only the first step towards calculating its value, but still a first step.
I suggest that the object-oriented approach will be that the Question object knows how to check an answer. Here is an implementation of the algorithm, simplified to the four operators, but extended to actually do the calculation:
public boolean checkAnswer(int answer) {
// calculate correct answer
// use shunting yard algorithm
Deque<Integer> outputQueue = new ArrayDeque<>();
Deque<Operator> operatorStack = new ArrayDeque<>();
for (QuestionElement element : questionElements) {
outputQueue.push(element.getValue());
Operator op = element.getOperator();
if (op != null) {
while (!operatorStack.isEmpty() && op.getPrecedence() <= operatorStack.peek().getPrecedence()) {
int operand2 = outputQueue.pop();
int operand1 = outputQueue.pop();
outputQueue.push(operatorStack.pop().apply(operand1, operand2));
}
operatorStack.push(op);
}
}
while (!operatorStack.isEmpty()) {
int operand2 = outputQueue.pop();
int operand1 = outputQueue.pop();
outputQueue.push(operatorStack.pop().apply(operand1, operand2));
}
int result = outputQueue.pop();
assert outputQueue.isEmpty();
return answer == result;
}
You notice that I have put some new demands on your Operator enum too. It has a precedence. And the + operator must know how to do addition (through its apply method), and similarly for the other operators:
PLUS("+", 1) {
#Override
public int apply(int operand1, int operand2) {
return operand1 + operand2;
}
},
// etc.
public abstract int apply(int operand1, int operand2);
and so on. 1 is the precedence; * and / have higher precedence, for example 2.
Now in main() you just need to write:
if (question.checkAnswer(answer)) {
If you decide to explain to the user that strict left-to-right evaluation is applied, it’s getting somewhat simpler:
public boolean checkAnswer(int answer) {
// calculate correct answer
// do left to right calculation
int result = questionElements.get(0).getValue();
for (int elementIndex = 1; elementIndex < questionElements.size(); elementIndex++) {
Operator op = questionElements.get(elementIndex - 1).getOperator();
result = op.apply(result, questionElements.get(elementIndex).getValue());
}
return answer == result;
}
The operators still need to have the apply method, but they no longer need the precedence.

Related

Calculator for metric distance from an expression that contains different scales

public enum Operator {
PLUS("+"),
MINUS("-");
private final String operator;
Operator(String operator) {
this.operator = operator;
}
public String getOperator() {
return operator;
}
public static Operator getByValue(String operator) {
for (Operator operatorEnum : Operator.values()) {
if (operatorEnum.getOperator().equals(operator)) {
return operatorEnum;
}
}
throw new IllegalArgumentException("Invalid value");
}
}
//////////
public enum MetricConvertor {
m(1000),
cm(10),
mm(1),
km(1000000),
dm(100);
private int scale;
MetricConvertor(int scale) {
this.scale = scale;
}
public int getScale() {
return scale;
}
}
/////////
public class Application {
public static void main(String[] args) {
int scale = MetricConvertor.valueOf("m").getScale();
}
I wan to create a calculator that is capable of computing a metric distance value from an expression that contains different scales and systems.
Output should be specified by the user.
Only Addition and subtraction is allowed.
Output is in lowest unit.
Expression: 10 cm + 1 m - 10 mm
Result: 1090 mm
I am stuck at this point, how can I add or substract the values for a list and convert them at the lowest scale sistem( eg above mm, but it can be dm if are added for example dm + m + km)
Here is solution
split each string by add/minus and add it to appropriate list
split number and metric in each list(can use matcher) and sum it
result = sumAdd - sumMinus(mm).
Please optimize it, because i don't have time to optimize this code, I need to go to bed :D
Result is in mm, so you have to get lowest metric and recaculate it(leave it to you).
private static int caculator(String exp) {
List<String> addList = new ArrayList<>();
List<String> minusList = new ArrayList<>();
int checkPoint = 0;
boolean op = true;//default first value is plus
// Split string with add/minus
for (int i = 1; i < exp.length(); i++) {
String s = exp.substring(i, i + 1);
if (Operator.PLUS.getOperator().equals(s)) {
checkOperator(addList, minusList, op, exp.substring(checkPoint, i).trim());
checkPoint = i + 1;
op = true;
continue;
}
if (Operator.MINUS.getOperator().equals(s)) {
checkOperator(addList, minusList, op, exp.substring(checkPoint, i).trim());
checkPoint = i + 1;
op = false;
continue;
}
}
// Add last string
checkOperator(addList, minusList, op, exp.substring(checkPoint).trim());
// Get sum each list
int sumAdd = sumList(addList);
int sumMinus = sumList(minusList);
return sumAdd - sumMinus;
}
//sum a list
private static int sumList(List<String> addList) {
int sum = 0;
for (String s: addList) {
String[] arr = s.split(" ");
int value = Integer.parseInt(arr[0]);
int scale = MetricConvertor.valueOf(arr[1]).getScale();
sum += value * scale;
}
return sum;
}
// check operator to put into approriate list
private static void checkOperator(List<String> addList, List<String> minusList, boolean op, String substring) {
if (op) {
addList.add(substring);
} else {
minusList.add(substring);
}
}

Polynomial program not working as expected

So I Created a class Term. This class represents a term of a polynomial such as 2x4 where 2 is coefficient and 4 is exponent of the
term.
Data members:-
int coefficient
int exponent
public class Term2 {
private int coefficient;
private int exponent;
public Term2() {
coefficient = 0;
exponent = 0;
}
public Term2(int coefficient, int exponent) {
this.coefficient = coefficient;
this.exponent = exponent;
}
public int getCoefficient() {
return coefficient;
}
public void setCoefficient(int coefficient) {
this.coefficient = coefficient;
}
public int getExponent() {
return exponent;
}
public void setExponent(int exponent) {
this.exponent = exponent;
}
}
then I Created another class called Polynomial. The internal representation of a polynomial is an array of Terms. The size of this array should be fixed. I
Provided a constructor for this class that will set all terms of a polynomial object as zero (where coefficient is 0 and exponent is 0).
then I created a funtion called
setTerm(int, int)
which Setting a term of a polynomial object. Each successive call of
this function should set next term of the polynomial object.
package javaapplication2;
import java.util.Scanner;
public class Polynomials {
private Term2 terms[];
private int valueLength = 0;
public Polynomials(int termSize) {
terms = new Term2[termSize];
for (int i = 0; i < terms.length; i++) {
terms[i] = new Term2(0, 0);
}
}
public void setTerm(int c, int e) {
if (valueLength >= terms.length) {
System.out.println("big");
return;
}
terms[valueLength++] = new Term2(c, e);
if (e > 0) {
for (int i = 0; i < terms.length; i++) {
terms[i] = new Term2(c, e);
}
}
}
public static void main(String[] args) {
int n;
System.out.println("Enter the number of terms : ");
Scanner in = new Scanner(System.in);
n = in.nextInt();
Polynomials p = new Polynomials(n);
p.setTerm(2, 3);
Term2 t = new Term2();
}
}
STUCKED
is the code structure is correct as I am not able to get the expected output in addtion i also want to achieve the two below funtionality
1.sort() ñ to arrange the terms in ascending order of exponents.
Provide a function to print a polynomial object
please suggest me the best solution
OUTPUT
run:
Enter the number of terms :
2
BUILD SUCCESSFUL (total time: 3 seconds)
The arrray is a too complicated data structure here. (Besides if (e > 0) { ... } messes things up.)
Either a Map from exponent to Term2 or to the coefficient.
public class Polynomials {
private SortedMap<Integer, Term2> termsByExponent = new TreeMap<>();
public Polynomials() {
}
public void setTerm(int c, int e) {
termsByExponent.put(e, new Term2(c, e));
}
/**
* #param exp the exponent (not the index).
*/
public Term2 getTerm(int exp) {
return termsByExponent.computeIfAbsent(exp, e -> new Term2(0, e));
}
public Term2 getTermByIndex(int i) {
return termsByExponent.values().get(i);
}
public int size() {
return map.size();
}
#Override
public String toString() {
return termsByExponent.values().stream()
.map(t -> String.format("%s%d.x^%d",
t.getCoefficient() >= 0 ? "+" : "", // Minus already there.
t.getCoefficient(),
t.getExponent()))
.collect(Collectors.join(""))
.replaceFirst("\\.x\\^0\\b", "")
.replaceFirst("\\^1\\b", "");
}
}

Trying to solve the derivative of a given equation from the user using ArrayList

As part of my AP computer science project, I decided to get a polynomial from a user and it will be able to find the derivative of the equation using the power rule.
For example, if the user enters 2X^3+5x^2 it should output 6x^2+10x^1, so the coefficient and degree multiplied together and then the degree is just minus one. This is what I have so far but it's giving me a lot of errors, and tried following the code but don't see anything wrong with it. Thanks for your help.
import java.util.ArrayList;
import java.util.Scanner;
public class Practice {
public static void main(String[] args) {
//input of polynomial
System.out.println("Enter polynomial:");
Scanner sc = new Scanner(System.in);
String polynomialEquation = sc.nextLine();
//A string array list is created with the polynomial
ArrayList<String> equationArr = new ArrayList<String>();
for (int i = 0; i<polynomialEquation.length(); i++) {
equationArr.add(polynomialEquation.substring(i, i+1));
}
ArrayList<String> intStrings = new ArrayList<String>();
//separate the numbers from the list
for(int i =0; i<equationArr.size(); i++) {
if (equationArr.get(i).equals("1") || equationArr.get(i).equals("2") || equationArr.get(i).equals("3") ||equationArr.get(i).equals("4") ||equationArr.get(i).equals("5") ||
equationArr.get(i).equals("6") || equationArr.get(i).equals("7") || equationArr.get(i).equals("8") || equationArr.get(i).equals("9") || equationArr.get(i).equals("0"))
{
String addVal = equationArr.get(i);
intStrings.add(addVal);
equationArr.remove(i);
}
}
//convert string integers to integers
ArrayList<Integer> deriveInt = new ArrayList<Integer>(intStrings.size());
for (String myInt : intStrings)
{
deriveInt.add(Integer.valueOf(myInt));
}
//derive coefficiants
for (int i = 0; i<deriveInt.size()-1;i +=2) {
deriveInt.set(i, deriveInt.get(i)*deriveInt.get(i+1));
}
//derive exponent
for(int i = 1; i< deriveInt.size(); i +=2) {
deriveInt.set(i,deriveInt.get(i)-1);
}
//convert integer back to string
ArrayList<String> stringDerive = new ArrayList<String>();
for (Integer myInt2 : deriveInt)
{
stringDerive.add(String.valueOf(myInt2));
}
//get the signs from the original equation
ArrayList<String> sign = new ArrayList<String>();
for(int i =0; i<equationArr.size(); i++) {
if(equationArr.get(i).equals("+") || equationArr.get(i).equals("-")) {
sign.add(equationArr.get(i));
}
}
int totalSize = stringDerive.size() * 2 + equationArr.size();
for (int i = 0; i<totalSize-1; i=+2) {
int countSign= 0;
System.out.print(stringDerive.get(i));
System.out.print("x^");
System.out.print(stringDerive.get(i+1));
System.out.print(equationArr.get(countSign));
}
}
}
Polynomials are composed of monomials. In your example these are 2X^3 and 5x^2. One of approach to solving your problem is writing the Monom class and Polynom class. I'll give you a skeleton so you can practice.
public class Helper {
private class Monom{
private int coefficient;
private int degree;
public Monom(int coefficient, int degree){
this.coefficient = coefficient;
this.degree = degree;
}
public Monom(String input){
//TODO parse input. E.g Monom("6x^2) --> this.coefficient = 6...
//TODO validate input
}
public Monom derivate(final Monom monom){
return new Monom(monom.getCoefficient() * monom.getDegree(), monom.getDegree() - 1);
}
public int getCoefficient() {
return coefficient;
}
public int getDegree() {
return degree;
}
#Override
public String toString(){
return this.coefficient + "x^" + this.degree;
}
}
//skeleton
private class Polynom{
private List<Monom> polynom; //holder of monoms
//TODO rest of code including constructors, validate, derivate...
public Polynom(List<Monom> monoms){
this.polynom = monoms;
}
public Polynom derivate(Polynom input){
List<Monom> temp = new ArrayList<>();
for (Monom monom: polynom){
temp.add(monom.derivate(monom));
}
return new Polynom(temp);
}
}
public static void main(String[] args) {
//TODO test code
List<Monom> monoms = new ArrayList<>();
//TODO rest of code like:
// Polynom myPolynom = new Polynom(List<Monom> monoms);
//...
}
}
Like I said, this is just a code you have to upgrade... Good luck.
welcome to Stack Overflow and the wonderful world of programming! On a personal note, I started coding in high school with APCS too :)
Your question is arguably a bit too broad for this site. For example, you mentioned the code is "giving me a lot of errors": a better question would include the inputs you've tried and the specific output you're seeing and what you expected instead. I still want to help you though, so I'll give you some feedback and we can work through a few revisions.
First, I see that you've divided your program into sections using comments. This is a great instinct! You've decomposed the larger problem into smaller problems in a way that communicates your intent.
input of polynomial
A string array list is created with the polynomial
separate the numbers from the list
convert string integers to integers
derive coefficiants
derive exponent
convert integer back to string
get the signs from the original equation
However, it still leaves us with the problem of having a large main method to understand. So for your next revision, you should fix that by breaking it up into smaller methods. You can start by moving each of these "steps" into its own method, then call each of them from main. To help you get started, here's what it would look like with your first "step" extracted:
public class Practice {
public static String readPolynomial() {
System.out.println("Enter polynomial:");
Scanner sc = new Scanner(System.in);
String polynomialEquation = sc.nextLine();
return polynomialEquation;
}
public static void main(String[] args) {
String polynomialEquation = readPolynomial();
//A string array list is created with the polynomial
...
}
}
I think you'll find that this really improves your understanding of both your code and the problem you're trying to solve. Don't be afraid to change the steps based on that new understanding. It's no coincidence that the buggy or unfocused areas of your code are the areas you'll struggle the most to name. Try to focus on the problem, rather than your implementation. For instance, my first step would probably be a combination of your first few. Things like parsing the input String and then converting from Strings to Integer don't have much to do with polynomials or derivatives. So for readPolynomial I would prefer:
public static ArrayList<Integer> readPolynomial() {
The other big benefit of this refactor is that it will be much easier for you to test that each step is working the way you want it to. It gives you much more fine-grained control because you can test each method individually, rather than only being able to test by running the entire program. It will be much easier to isolate, understand, and fix each individual bug.
Another big thing: please provide some more sample inputs! Not only will this help clarify requirements, but we can use them as test cases later.
Here's some functioning code to help you, please don't just take it for granted but read it and understand what is happening. If you have any questions on it please ask. It could use some cleanup but hopefully it's still understandable.
One minor thing to note is that sign is attached to the expressions (as it kinda should be) so you could just + all the expressions together and it would be valid. But if you want to avoid having an answer like 6x^2 + -10y^4 and would rather have 6x^2 - 10y^4 then you'd have to check if the expressions are negative when building the answer with them.
public class Test {
public static void main(String[] args) {
// input requires all constants to be fully resolved
// eg. no '3^2^1^3', instead it should be '9'
// eg. no '5*2x', instead it should be '10x'
// mess around with the input to test
String s = "2x^3+5x^2";
List<DerivableExpression> list = parseDeriveableExpressions(s);
List<DerivableExpression> derivatives = new ArrayList<>();
for(DerivableExpression de : list)
derivatives.add(de.getDerivative());
System.out.println(String.join("+", derivatives)); // 6x^2+10x^1
}
private static List<DerivableExpression> parseDeriveableExpressions(String s) {
// remove all spaces and lowercase everything
s = s.replace(" ", "");
List<DerivableExpression> list = new ArrayList<>();
char var = ' ';
StringBuilder constBuff = new StringBuilder();
StringBuilder powerBuff = new StringBuilder();
boolean parsingPower = false;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '+' || c == '-') {
if (parsingPower && powerBuff.length() == 0) {
// at the start of the power expression
if (c == '-')
powerBuff.append(c);
} else {
// either not parsing a power or not at the start of the power
// this is a +/- after the power, terminating the expression
parsingPower = false;
int constant = 1;
if (constBuff.length() > 0) {
constant = Integer.parseInt(constBuff.toString());
constBuff.setLength(0);
}
if (var != ' ' && constant != 0) {
int power = 1;
if (powerBuff.length() > 0)
power = Integer.parseInt(powerBuff.toString());
list.add(new VariableExpression(constant, var, power));
} else {
list.add(new ConstantExpression(constant));
}
powerBuff.setLength(0);
var = ' ';
// append the sign for the next expression
if (c == '-')
constBuff.append(c);
}
} else if ('0' <= c && c <= '9') {
if (parsingPower)
powerBuff.append(c);
else
constBuff.append(c);
} else if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) {
if (constBuff.length() == 0 ||
(constBuff.length() == 1 && constBuff.charAt(0) == '-'))
constBuff.append("1");
var = c;
} else if (c == '^') {
parsingPower = true;
}
}
// add the last expression
int constant = 1;
if (constBuff.length() > 0) {
constant = Integer.parseInt(constBuff.toString());
constBuff.setLength(0);
}
if (var != ' ') {
int power = 1;
if (powerBuff.length() > 0) {
power = Integer.parseInt(powerBuff.toString());
powerBuff.setLength(0);
}
list.add(new VariableExpression(constant, var, power));
var = ' ';
} else {
list.add(new ConstantExpression(constant));
}
return list;
}
private static interface DerivableExpression {
public abstract DerivableExpression getDerivative();
}
private static class VariableExpression implements DerivableExpression {
private final int constant;
private final char variable;
private final int power;
public VariableExpression(int constant, char variable, int power) {
this.constant = constant;
this.variable = variable;
this.power = power;
}
#Override public VariableExpression getDerivative() {
return new VariableExpression(constant * power, variable, power - 1);
}
#Override public String toString() { return constant + "" + variable + "^" + power; }
}
private static class ConstantExpression implements DerivableExpression {
private final int constant;
public ConstantExpression(int constant) {
this.constant = constant;
}
#Override public DerivableExpression getDerivative() { return this; }
#Override public String toString() { return Integer.toString(constant); }
}
}

Recursive algorithm stops working after certain depth

I was exploring Fork/Join framework and its possible speed benefits through factorial counting, when discovered that my sequential recursive algorithm breaks at a certain point. To be precise, when I try to count 46342! the result from RecursiveCounter is wrong, but before that value it is always right and is the same that result from ParallelCounter and LoopCounter. Does anyone have an idea why that may happen?
Here are the classes:
RecursiveCounter:
public class RecursiveCounter implements FactorialCounter, RangeFactorialCounter {
#Override
public BigInteger count(int number) {
return count(1, number);
}
#Override
public BigInteger count(int from, int to) {
int middle = (from + to) >> 1;
BigInteger left;
BigInteger right;
if (middle - from > 1)
left = count(from, middle);
else
left = new BigInteger(String.valueOf(from * middle));
if (to - (middle + 1) > 1)
right = count(middle + 1, to);
else
right = to == middle + 1 ? new BigInteger(String.valueOf(to)) : new BigInteger(String.valueOf((middle + 1) * to));
return left.multiply(right);
}
}
LoopCounter:
public class LoopCounter implements FactorialCounter, RangeFactorialCounter {
#Override
public BigInteger count(final int number) {
return count(1, number);
}
#Override
public BigInteger count(final int from, final int to) {
BigInteger result = new BigInteger("1");
for (int i = from; i < to + 1; i++) {
result = result.multiply(new BigInteger(String.valueOf(i)));
}
return result;
}
}
A RecursiveTask for ParallelCounter:
public class FactorialTask extends RecursiveTask<BigInteger> {
private static final int THRESHOLD = 1000;
private RangeFactorialCounter iterativeCounter = new LoopCounter();
private Integer firstVal;
private Integer lastVal;
public FactorialTask(Integer from, Integer to) {
super();
this.firstVal = from;
this.lastVal = to;
}
#Override
protected BigInteger compute() {
return count(firstVal, lastVal);
}
private BigInteger count(int from, int to) {
int middle = (from + to) >> 1;
if (to - from > THRESHOLD) {
List<FactorialTask> tasks = Arrays.asList(new FactorialTask(from, middle), new FactorialTask(middle + 1, to));
tasks.forEach(RecursiveTask::fork);
return tasks.stream()
.map(RecursiveTask::join)
.map(BigInteger.class::cast)
.reduce(new BigInteger("1"), BigInteger::multiply);
} else {
return (from != to) ? countSequential(from, to) : new BigInteger(String.valueOf(from));
}
}
private BigInteger countSequential(int from, int to) {
return iterativeCounter.count(from, to);
}
}
In RecursiveCounter, from * middle and (middle + 1) * to might overflow, you need use BigInteger to manipulate them:
...
left = BigInteger.valueOf(from).multiply(BigInteger.valueOf(middle));
...
right = to == middle + 1 ? BigInteger.valueOf(to) : BigInteger.valueOf(to).multiply(BigInteger.valueOf(middle + 1));
Then you can get the same result in RecursiveCounter and LoopCounter:
LoopCounter loopCounter = new LoopCounter();
RecursiveCounter recursiveCounter = new RecursiveCounter();
BigInteger loopResult = loopCounter.count(46342);
BigInteger recursiveResult = recursiveCounter.count(46342);
System.out.println(loopResult.equals(recursiveResult)); // true
This happens because of numeric overflow of an int, not because of recursive depth, which is nicely controlled by your algorithm, which needs O(log2n) stack frames for recursion.
The overflow happens here:
new BigInteger(String.valueOf((middle + 1) * to))
When to is high, this value can overflow int. Specifically, when middle approaches to in the second "leg" of recursive invocations, you multiply 46341 by 46342, which yields -2147432674 due to an overflow (demo).
You can fix this by using only BigInteger for "payload" multiplication, i.e.
BigInteger.valueOf(middle+1).multiply(BigInteger.valueOf(to))

How to print out a toString for this class?

I have written a polynomial class and a tester class. The polynomial class can evaluate and return the sum of the polynomial when the degree, coefficients and the value of x are provided. Basically I need to edit my toString method so it actually prints out the polynomial
import java.util.Arrays;
import java.util.Scanner;
public class Polynomial {
private int degree;
private int [] coefficient;
private double evaluation;
private double sum;
private double value;
Scanner key = new Scanner(System.in);
public Polynomial(int degree)
{
this.degree = degree;
coefficient = new int [degree+1];
}
public void setCoefficient(int coefficient)
{
this.coefficient[this.degree] = coefficient;
}
public int getCoefficient(int degree)
{
return coefficient[degree];
}
public double Evaluate(double value)
{
this.value =value;
for (int i=0; i<=degree; i++)
{
System.out.println("Enter coefficent for position " + i);
this.coefficient[i] = key.nextInt();
evaluation = Math.pow(value, i)*this.coefficient[0] ;
this.sum += evaluation;
}
return sum;
}
/** Standard toString method */
//needed something better than this below...needed an actual polynomial printed out
public String toString()
{
return "The degree of the polynomial is " + degree + " and the value for which it has been evaluated is" + value;
}
}
This should be along the lines you should be proceeding. I included the main function in your Polynomial class for simplicity, so you will have to modify that if you want to keep it in your tester class. Notice that degree has been made into an integer array of size degree +1(allocated in the constructor):
import java.util.Scanner;
public class Polynomial {
private int degree;
private int [] coefficient;
private double evaluation;
private double sum;
Scanner key = new Scanner(System.in);
public Polynomial(int degree)
{
this.degree = degree;
coefficient = new int [degree+1];
}
public void setCoefficient(int coefficient, int degree)
{
this.coefficient[degree] = coefficient;
}
public int getCoefficient(int degree)
{
return coefficient[degree];
}
public void Evaluate(double value)
{
for (int i=0; i<=degree; i++)
{
System.out.println("Enter coefficent for position " + i);
this.coefficient[i] = key.nextInt();
evaluation = Math.pow(value, i)*this.coefficient[0] ;
this.sum += evaluation;
}
}
public double getSum(){
return sum;
}
public String toString()
{
String s = "";
for (int i=0; i <= degree; i++)
{
s += coefficient[i];
switch (i) {
case 0:
s += " + ";
break;
case 1:
s += "x + ";
break;
default:
s += "x^" + i + ((i==degree)?"":" + ");
}
}
return s;
}
public static void main(String[] args) {
int degree;
double sum;
int coefficient;
Scanner key = new Scanner(System.in);
System.out.println("Enter the degree of the polynomial");
degree=key.nextInt();
Polynomial fun = new Polynomial(degree);
fun.Evaluate(3.0);
System.out.println(" The sum of the polynomial is " + fun.getSum());
System.out.println(fun);
}
}
The usual way of making the objects of a class printable is to supply a toString method in the class, which specifies how to express objects of that class as a String. Methods such as println and other ways of outputting a value will call a class's toString method if they need to print an object of that class.
You should adopt the same pattern with your Polynomial class - write a toString method with all the output logic. Then in your PolynomialTester class, all you need to write is System.out.println(fun); and the rest will just happen. You'll find this far more versatile than writing a method that actually does the printing. For example, you'll be able to write something like
System.out.println("My polynomial is " + fun + " and " + fun + " is my polynomial.");
if that's your idea of fun.
A few other things concern me about your class.
You seem to be only storing one coefficient and one exponent. I'd expect a polynomial to have a whole array of coefficients.
You have fields for evaluation and sum - but these only really make sense while a polynomial is being evaluated. They're not long-term properties of the polynomial. So don't store them in fields. Have them as local variables of the evaluate method, and return the result of the evaluation.
I'd expect a class like this to be immutable. That is, you should provide all the coefficients when the object is created, and just never change them thereafter. If you do it that way, there's no need to write setter methods.
So I've written my own version of your class, that fixes those issues listed above, and implements a toString method that you can use for printing it. A second version of toString lets you specify which letter you want to use for x. I've used "varargs" in the constructor, so you can construct your polynomial with a line such as
Polynomial fun = new Polynomial (7, 2, 5, 0, 1);
specifying the coefficients from the constant term through in order to the coefficient of the term with the highest exponent. Or you can just pass an array.
See that I've changed the logic a wee bit - my version prints the polynomial in the conventional order, from highest to lowest exponent. It leaves off the decimals if the coefficient is an integer. It doesn't print a 1 in front of an x. And it deals cleanly with - signs.
import java.util.Arrays;
public class Polynomial {
private double[] coefficients;
public Polynomial(double... coefficients) {
this.coefficients = Arrays.copyOf(coefficients, coefficients.length);
}
public int getDegree() {
int biggestExponent = coefficients.length - 1;
while(biggestExponent > 0 && coefficients[biggestExponent] == 0.0) {
biggestExponent--;
}
return biggestExponent;
}
public double getCoefficient(int exponent) {
if (exponent < 0 || exponent > getDegree()) {
return 0.0;
} else {
return coefficients[exponent];
}
}
public double evaluateAt(double x) {
double toReturn = 0.0;
for (int term = 0; term < coefficients.length; term++) {
toReturn += coefficients[term] * Math.pow(x, term);
}
return toReturn;
}
#Override
public String toString() {
return toString('x');
}
public String toString(char variable) {
boolean anythingAppendedYet = false;
StringBuilder toReturn = new StringBuilder();
for (int exponent = coefficients.length - 1; exponent >= 0; exponent--) {
if (coefficients[exponent] != 0.0) {
appendSign(toReturn, exponent, anythingAppendedYet);
appendNumberPart(toReturn, exponent);
appendLetterAndExponent(toReturn, exponent, variable);
anythingAppendedYet = true;
}
}
if (anythingAppendedYet) {
return toReturn.toString();
} else {
return "0";
}
}
private void appendSign(StringBuilder toAppendTo, int exponent, boolean anythingAppendedYet) {
if (coefficients[exponent] < 0) {
toAppendTo.append(" - ");
} else if (anythingAppendedYet) {
toAppendTo.append(" + ");
}
}
private void appendNumberPart(StringBuilder toAppendTo, int exponent) {
double numberPart = Math.abs(coefficients[exponent]);
if (numberPart != 1.0 || exponent == 0) {
//Don't print 1 in front of the letter, but do print 1 if it's the constant term.
if (numberPart == Math.rint(numberPart)) {
// Coefficient is an integer, so don't show decimals
toAppendTo.append((long) numberPart);
} else {
toAppendTo.append(numberPart);
}
}
}
private void appendLetterAndExponent(StringBuilder toAppendTo, int exponent, char variable) {
if (exponent > 0) {
toAppendTo.append(variable);
}
if (exponent > 1) {
toAppendTo.append("^");
toAppendTo.append(exponent);
}
}
}
So I tested it with this class
public class PolynomialTester {
public static void main(String[] args) {
Polynomial fun = new Polynomial (7, 2, 5, 0, 1);
System.out.println(fun.getDegree());
System.out.println(fun.evaluateAt(3));
System.out.println(fun);
}
}
and the output was
4
139.0
x^4 + 5x^2 + 2x + 7
then I realised that you wanted to be able to input the coefficients in a loop. So I changed PolynomialTester to this. See how I build the array and then create the object.
import java.util.Scanner;
public class PolynomialTester {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Enter the degree:");
int degree = input.nextInt();
double[] coefficients = new double[degree + 1];
for( int exponent = 0; exponent <= degree; exponent++) {
System.out.println("Enter the coefficient of x^" + exponent);
coefficients[exponent] = input.nextDouble();
}
Polynomial fun = new Polynomial (coefficients);
System.out.println(fun.evaluateAt(3));
System.out.println(fun);
input.close();
}
}
Note that if you really want your polynomial to be printed in "reverse" order, with the constant term first, you could change the loop in the toString method to this.
for (int exponent = 0; exponent < coefficients.length; exponent++) {
You may add a class member String poly, then modify the following method.
public void Evaluate(double value)
{
for (int i=0; i<=degree; i++)
{
System.out.println("Enter coefficent for position " + i);
this.coefficient= key.nextInt();
evaluation = Math.pow(value, i)*coefficient ;
this.sum += evaluation;
this.poly = "";
if(coefficient != 0)
{
if(i > 0)
{
this.poly += " + " + Integer.toString(coefficient) + "x^" + Integer.toString(i); // you may replace x with the actual value if you want
}
else
{
this.poly = Integer.toString(coefficient)
}
}
}
}

Categories

Resources