So here's my Code:
public double evaluate(){
Stack numbers = new Stack();
Stack operators = new Stack();
String[] divert = {};
String problem = "2 + 2 + 3";
divert = problem.split(" ");
for(int i = 0; i < divert.length; i++){
if(divert[i].equals("*") || divert[i].equals("/")|| divert[i].equals("+") || divert[i].equals("-")){
if(operators.peek().equals("*") || operators.peek().equals("/")){
int a = Integer.parseInt((String)numbers.pop());
int b = Integer.parseInt((String)numbers.pop());
String operand = (String)operators.pop();
numbers.push(doMath(b, operand, a));
}
else if ( divert[i].equals("+") || divert[i].equals("-")){
operators.push(divert[i]);
}
} else {
numbers.push(divert[i]);
}
}
while(!operators.empty()){
int a = Integer.parseInt((String)numbers.pop());
int b = Integer.parseInt((String)numbers.pop());
String operand = (String)operators.pop();
numbers.push(doMath(a, operand, b));
}
double endNumber = (double)numbers.pop();
return endNumber;
}
I keep getting weird errors, one telling me that the if(operators.peek().equals... bit in the nested if statement returns an EmptyStackException.
I get another error while trying to cast the popped number (endNumber) off to return it. I get an issue with casting that as a double.
If someone would look at this and tell me what is the problems and any possible way to resolve the issue, that would be great because I really don't understand why it's giving me these errors.
I know that removing the divert[i].equals("+")/("-") removes the issue for the first error, but that isn't very conductive to what I'm doing.
For the problem with doubles use the generics capability of Stack
Stack<Double> numbers = new Stack<Double>();
this will ensure only Doubles are stored on the stack. The auto unboxing (converts doubles to Doubles and visa-versa) feature means you should be able to do
double x = 5.0;
numbers.push(x);
double y = numbers.pop();
For good form also use
Stack<String> operator;
For testing the operator stack use
if( !operators.empty() && (operators.peek().equals("*") || operators.peek().equals("/")) )
i.e. test if the stacks is not empty before peeking.
Also check the order you popping numbers off the stack, in the code at the end. I've a feeling you will have problems with "5 - 3".
Also you always want to push the current operator. It looks like a "*" or "/" will never get pushed.
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
I'm creating a program. This code below is the Java program. Checking if the value of B and H, input by the user is equal to zero. If it is true, then a math formula will execute which is p = b*h then if it is false, a string will be shown on the console. But the thing is, it keeps on giving me an error that string cannot be converted to int or int cannot be converted to string.
Here is the code:
import java.util.Scanner;
public class StaticProject{
static {
Scanner input = new Scanner (System.in);
int B = input.nextInt();
int H = input.nextInt();
int P;
int solution = B>=0 && H>=0 ? P = B*H : "java.lang.Exception: Breadth and height must be positive";
}
How can I improve my coding when it comes in doing this oneline bi-conditionals statement? Any tips?
your solution variable Type is int, and your else statement returns an String, this is the cause of error.
you can change your code to this:
Scanner input = new Scanner (System.in);
int B = input.nextInt();
int H = input.nextInt();
int P;
if (B >= 0 && H >= 0) {
P = B*H;
} else {
throw new Exception("Breadth and height must be positive");
}
System.out.println(P);
}
You are trying to assign string to an int variable, if your statement is evaluated as false.
You need to use if/else condition, which both sides have the same type.
In your case, it's not possible.
another possibility is use System.out.println() command, to print the result of whatever resulted by the condition.
There is no virtue in writing code in as few lines as possible. By all means, don't write unnecessary code, but just don't think that concise code is objectively "better".
The best type of code to write is simple code. Maybe it's a little more verbose; but if you write code that people can understand at a glance, they know what it does straight away.
Here is how I would write it:
if (B < 0 || H < 0) {
// Actually, non-negative, rather than positive.
throw new Exception("Breadth and height must be positive");
// Or, maybe, don't even use exceptions at all:
// System.out.println("The message");
// return;
}
// No need for `solution` variable.
P = B * H;
System.out.println(P);
Of course, you might argue this isn't code everybody will understand at a glance. Sure. Readability is subjective; but I assert that anybody with just a little bit of experience in Java can work it out.
You can write a conditional ?: expression which results in an exception being thrown in the case of the condition being false.
// Define a method which does the throwing.
static int justThrow(String message) throws Exception {
throw new Exception(message);
}
// In the main method:
int solution = B>=0 && H>=0 ? P = B*H : justThrow("Breadth and height must be positive");
I emphasize that you can, but you shouldn't do this. It's obscure. It's trying to be "a bit too clever". It will have people reading your code and scratching their heads, because they will wonder why you wrote a method for something so simple; what is the solution variable for, given that it will have the same value as P etc.
QUESTION:
How can I read the string "d6+2-d4" so that each d# will randomly generate a number within the parameter of the dice roll?
CLARIFIER:
I want to read a string and have it so when a d# appears, it will randomly generate a number such as to simulate a dice roll. Then, add up all the rolls and numbers to get a total. Much like how Roll20 does with their /roll command for an example. If !clarifying {lstThen.add("look at the Roll20 and play with the /roll command to understand it")} else if !understandStill {lstThen.add("I do not know what to say, someone else could try explaining it better...")}
Info:
I was making a Java program for Dungeons and Dragons, only to find that I have come across a problem in figuring out how to calculate the user input: I do not know how to evaluate a string such as this.
I theorize that I may need Java's eval at the end. I do know what I want to happen/have a theory on how to execute (this is more so PseudoCode than Java):
Random rand = new Random();
int i = 0;
String toEval;
String char;
String roll = txtField.getText();
while (i<roll.length) {
check if character at i position is a d, then highlight the numbers
after d until it comes to a special character/!aNumber
// so if d was found before 100, it will then highlight 100 and stop
// if the character is a symbol or the end of the string
if d appears {
char = rand.nextInt(#);
i + #'s of places;
// so when i++ occurs, it will move past whatever d# was in case
// d# was something like d100, d12, or d5291
} else {
char = roll.length[i];
}
toEval = toEval + char;
i++;
}
perform evaluation method on toEval to get a resulting number
list.add(roll + " = " + evaluated toEval);
EDIT:
With weston's help, I have honed in on what is likely needed, using a splitter with an array, it can detect certain symbols and add it into a list. However, it is my fault for not clarifying on what else was needed. The pseudocode above doesn't helpfully so this is what else I need to figure out.
roll.split("(+-/*^)");
As this part is what is also tripping me up. Should I make splits where there are numbers too? So an equation like:
String[] numbers = roll.split("(+-/*^)");
String[] symbols = roll.split("1234567890d")
// Rough idea for long way
loop statement {
loop to check for parentheses {
set operation to be done first
}
if symbol {
loop for symbol check {
perform operations
}}} // ending this since it looks like a bad way to do it...
// Better idea, originally thought up today (5/11/15)
int val[];
int re = 1;
loop {
if (list[i].containsIgnoreCase(d)) {
val[]=list[i].splitIgnoreCase("d");
list[i] = 0;
while (re <= val[0]) {
list[i] = list[i] + (rand.nextInt(val[1]) + 1);
re++;
}
}
}
// then create a string out of list[]/numbers[] and put together with
// symbols[] and use Java's evaluator for the String
wenton had it, it just seemed like it wasn't doing it for me (until I realised I wasn't specific on what I wanted) so basically to update, the string I want evaluated is (I know it's a little unorthodox, but it's to make a point; I also hope this clarifies even further of what is needed to make it work):
(3d12^d2-2)+d4(2*d4/d2)
From reading this, you may see the spots that I do not know how to perform very well... But that is why I am asking all you lovely, smart programmers out there! I hope I asked this clearly enough and thank you for your time :3
The trick with any programming problem is to break it up and write a method for each part, so below I have a method for rolling one dice, which is called by the one for rolling many.
private Random rand = new Random();
/**
* #param roll can be a multipart roll which is run and added up. e.g. d6+2-d4
*/
public int multiPartRoll(String roll) {
String[] parts = roll.split("(?=[+-])"); //split by +-, keeping them
int total = 0;
for (String partOfRoll : parts) { //roll each dice specified
total += singleRoll(partOfRoll);
}
return total;
}
/**
* #param roll can be fixed value, examples -1, +2, 15 or a dice to roll
* d6, +d20 -d100
*/
public int singleRoll(String roll) {
int di = roll.indexOf('d');
if (di == -1) //case where has no 'd'
return Integer.parseInt(roll);
int diceSize = Integer.parseInt(roll.substring(di + 1)); //value of string after 'd'
int result = rand.nextInt(diceSize) + 1; //roll the dice
if (roll.startsWith("-")) //negate if nessasary
result = -result;
return result;
}
How would you efficiently (optimizing for runtime but also keeping space at a minimum) parse and evaluate a single digit arithmetic expression in Java.
The following arithmetic expressions are all valid:
eval("-5")=-5
eval("+4")=4
eval("4")=4
eval("-7+2-3")=-8
eval("5+7")=12
My approach is to iterate over all elements, keeping track of the current arithmetic operation using a flag, and evaluate digit by digit.
public int eval(String s){
int result = 0;
boolean add = true;
for(int i = 0; i < s.length(); i++){
char current = s.charAt(i);
if(current == '+'){
add = true;
} else if(current == '-'){
add = false;
} else {
if(add){
result += Character.getNumericValue(current);
} else {
result -= Character.getNumericValue(current);
}
}
}
return result;
}
Is this the only optimal solution? I have tried to use stacks to keep track of the arithmetic operator, but I am not sure this is any more efficient. I also have not tried regular expressions. I only ask because I gave the above solution in an interview and was told it is sub-optimal.
This seems a bit more compact. It certainly requires fewer lines and conditionals. The key is addition is the "default" behavior and each minus sign you encounter changes the sign of what you want to add; provided you remember to reset the sign after each addition.
public static int eval(String s){
int result = 0;
int sign = 1;
for(int i = 0; i < s.length(); i++){
char current = s.charAt(i);
switch (current)
{
case '+': break;
case '-': sign *= -1; break;
default:
result += sign * Character.getNumericValue(current);
sign = 1;
break;
}
}
return result;
}
As a note, I don't think yours produces correct results for adding a negative, e.g., "4- -3". Your code produces 1, rather than the correct value of 7. On the other hand, mine allows expressions such as "5+-+-3", which would produce the result 8 (I suppose that's correct? :). However, you didn't list validation as a requirement and neither of us are checking for sequential digits, alpha characters, white space, etc. If we assume the data is properly formatted, the above implementation should work. I don't see how adding data structures (such as queues) could possibly be helpful here. I'm also assuming just addition and subtraction.
These test cases produce the following results:
System.out.println(eval("1+2+3+4"));
System.out.println(eval("1--3"));
System.out.println(eval("1+-3-2+4+-3"));
10
4
-3
You need to lookup up 'recursive descent expression parser' or the Dijkstra shunting-yard algorithm. Your present approach is doomed to failure the moment you have to cope with operator precedence or parentheses. You also need to forget about regular expressions and resign yourself to writing a proper scanner.
I have been building a simple formula calculator and have gotten stuck with addition and subtraction. As you should know, when calculating an equation, you follow the arithmetic rules of precedence, i.e. brackets, order: power functions, division, multiplication, addition and subtraction. The problem is that addition and subtraction are given equal priority, so therefore you can read it from left to right. Here is my code so far:
{
ArrayList<String> equation = java.util.Arrays.asList({"2","-","2","+","5"});
while(equation.contains("+")){
addMe(equation);
}
while(equation.contains("-")){
minusMe(equation);
}
}
public static void addMe(ArrayList<String> numberList){
for (int i = 0, n = numberList.size(); i < n; i++) {
String value = (String) numberList.get(i);
if(value.equals("+")){
String wordBefore = (String) numberList.get(i-1);
String wordAfter = (String) numberList.get(i+1);
System.out.println("This is the word before " + wordBefore);
System.out.println("This is the word after " + wordAfter);
double doubleFromBefore = Double.parseDouble(wordBefore);
double doubleFromAfter = Double.parseDouble(wordAfter);
double answer = doubleFromBefore + doubleFromAfter;
System.out.println("This is the answer: " + answer);
String stringAnswer = String.valueOf(answer);
String newNum2 = value.replace(value, stringAnswer);
numberList.set(i,newNum2);
numberList.remove(i-1);
numberList.remove(i);
break;
}
}
}
The minusMe method is exactly the same as the addMe method except with "-" in relevant places. The problem I am having is getting the equation read from left to right one item at a time and either doing the add or subtract method. Ideally I think I need to combine my 2 while loops with an iterator, to solve the problem but my attempts haven't worked. Any idea as to if this will solve my problem? If so please provide amended loop.
Regards
Have a look at this
java.uti.ArrayList<String> equation = java.util.Arrays.asList({"2","-","2","+","5"});
java.util.Iterator<String> equIterator = equation.iterator();
int result = 0;
int multiplier = 1;
while(equIterator.hasNext()){
String operandOrOperator = equIterator.next();
if(operandOrOperator.equals("+")){
multiplier=1;
}else if(operandOrOperator.equals("-")){
multiplier=-1;
}else if(operandOrOperator.equals("*")){
result*=Integer.parseInt(equIterator.next()); // Assuming that next element will be there always after operator.
}else{
result+=(multiplier * Integer.parseInt(operandOrOperator));
}
}
System.out.println("Final result : " + result);
You are doing this all wrong. You need to use at least a recursive-descent expression parser, or Dijkstra's shunting-yard algorithm, maybe even a parser generator if this is going to grow into some kind of a language. You will find all these things via a web search.
public static int intersectionSizeMergeAndSort(studentList L1, studentList L2) {
int intersectionSize = 0;
int[] C = new int[L1.studentID.length+L2.studentID.length];
for(int i = 0; i<L1.studentID.length; i++){
C[i] = L1.studentID[i];
}
for(int i = 0; i<L2.studentID.length; i++){
C[i+L1.studentID.length] = L2.studentID[i];
}
Arrays.sort(C);
int pointer = 0;
while(pointer<((L1.studentID.length)+(L2.studentId.length))){
if(C[pointer] = C[pointer+1]){
intersectionSize = intersectionSize + 1;
pointer = pointer + 2;
}
else {
pointer == pointer + 1;
}
return intersectionSize;
}
}
I have this algorithm I am writing for an assignment. Every time I compile my code, I get an error that I cannot understand in order to debug.
Error is as follows:
Error: /Users/nah/Desktop/studentList.java:137: operator < cannot be applied to int,<nulltype>
the error is pointing to the while loop statement
Not sure if this is directly related to the same error but your line
while(pointer<((L1.studentID.length)+(L2.studentId.length))){
has mis-spelt the second "studentId" and should be "studentID"
while(pointer<((L1.studentID.length)+(L2.studentID.length))){
that is of course unless you happen to have two arrays defined for your studentID class, each with a different case.
I also agree with the other answers related to the "==" comparison operator, but you're telling us the error is related to the while statement
The only error I can see is:
if(C[pointer] = C[pointer+1]){
this should be:
if(C[pointer] == C[pointer+1]){
The following will not work in Java:
if (C[pointer] = C[pointer+1])
This is assignment, its type is int, it cannot be used in the if statement
While loop ? Ok. Debugging is done by simplifying expressions.
The only thing where we see < is the loop condition. Instead of
int pointer = 0;
while(pointer<((L1.studentID.length)+(L2.studentId.length))){
do
int pointer = 0;
int len = ((L1.studentID.length)+(L2.studentId.length));
while(pointer< len){
If error again, simplify the error-raising expression.
I think that this question is mistitled. It is ** ambigous only because you do not attempt to localize it. Post a question only if "<" does not work for two integers. The current question title must be: "how do you debug Java programs?"