First time posting so please inform me of how to improve.
I'm working on a program to convert infix notation to postfix and then evaluate. My conversion to postfix went well, but I'm having some trouble with my evaluation. In the code below, when I try to convert the operands into a double variable 'number' they don't maintain their value (see runtime output below). Here is part of the method in question (the print statements are for debugging only).
public boolean evaluatePostfix(StringBuffer postfix)
{
Stack <Double> operand = new Stack <Double>();//stack to hold operand values
double answer = 0; //variable to hold result of expression
boolean error = false; //tests for input error
int pos = 0; //temp veraible stores position in postfix expression
double number = 0; //temp variable to convert char to double. also stores that value for reference
double val1 = 0; //first value for operations
double val2 = 0; //second value for operations
double val3 = 0; //answer for val1 and val2
while (!error && pos < postfix.length())
{
System.out.println(postfix.charAt(pos));
if (postfix.charAt(pos) == ' ')
; //do nothing
else if (Character.isDigit(postfix.charAt(pos)))
{
number = Double.parseDouble(postfix.substring(pos));
System.out.printf ("number = %f", number);
operand.push(number);
}
else
{
val1 = operand.pop();
val2 = operand.pop();
System.out.printf ("val1: %f\tval2: %f\n", val1, val2);
---At runtime--- 1
number = 49.000000
8
number = 56.000000
+
val1: 56.000000
val2: 49.000000
val3 = 105.000000
105.0
You are taking the ASCII value of each character e.g. '1' => 49 and pushing it on to the stack.
Most likely what you want is to use a Scanner to read numbers converted from the text you input.
Replace:
number = postfix.charAt(pos);
with:
number = Double.parseDouble(Character.toString(postfix.charAt(pos)));
The Double.parseDouble method converts the string in double:
Returns a new double initialized to the value represented by the
specified String, as performed by the valueOf method of class Double.
(from Javadoc)
If you split the String with postfix.toString.split(" ") and then iterate on the string[] you will be able to parse also double values (like "8.4567"):
String[] sa = postfix.toString().split(" ");
for (String string : sa) {
.... omissis ...
otherwise your code will be correct only parsing single digit integer values.
Parsing an expression may not be a trivial task. In more complex cases using a parser generator is the only reasonable approach.
In your case, you might do without one:
What are your 'tokens'?
How do you detect the start and end of each token?
Once you have your tokens extracted from the input, what do you do with each of them?
Your tokens appear to be (decimal) numbers and arithmetic operators. - How can you determine the start and end of each? Whitespaces " " between them may make a sufficient delimiter.
Then you can cleanly parse your tokens one at a time: Use Double.parseDouble(...) to parse the numerical tokens and process the operators accordingly.
You may want to have a look at Java's Tokenizer for support in extracting the tokens from the input.
Related
I want to parse a string and get a double value.
For example, I input "65.2 hello".
I want to get "65.2"
Will I?
while(scanner.hasNextLine()) {
String ReadString = scanner.nextLine();
double value = Double.parseDouble(ReadString);
Exception in thread "main" java.lang.NumberFormatException: For input string: "65.2 hello"
at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2054)
at java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
at java.base/java.lang.Double.parseDouble(Double.java:549)
at com.company.Main.main(Main.java:18)
Because at least part of the String can't be converted to a double, you need to remove that part of the String before you can use parseDouble on it.
Try this.
Scanner scanner = new Scanner("65.2 hello");
while(scanner.hasNextDouble()) {
double value = scanner.nextDouble();
System.out.println(value);
}
output:
65.2
For a simple string like "65.2 hello" where there is one numerical value within the string then a simple:
String myString = "65.2 hello";
double value = Double.parseDouble(myString.replaceAll("[^(-?\\d+(\\.\\d+)?)]", "").trim());
should be suffice. But, if there is more than one numerical value within the string then you would need to change it up a little, for example:
String myString = "I weigh 90.7185kg and I would like to loose another 10kg. "
+ "My name is Tom, I'm 32 years old.";
String parsable = myString.replaceAll("[^(-?\\d+(\\.\\d+)?)]", " ").trim()
.replaceAll("\\s\\p{Punct}|\\p{Punct}\\s", "");
double[] values = {};
if (!parsable.isEmpty()) {
String[] numbers = parsable.split("\\s+");
values = new double[numbers.length];
for (int i = 0; i < numbers.length; i++) {
values[i] = Double.parseDouble(numbers[i]);
}
}
// Display doubles array into Console Window:
for (int i = 0; i < values.length; i++) {
System.out.println("Value #" + (i + 1) + " in String is: -> " + values[i]);
}
About the Regular Expressions (regex's) used in this line:
String parsable = myString.replaceAll("[^(-?\\d+(\\.\\d+)?)]", " ").trim()
.replaceAll("\\s\\p{Punct}|\\p{Punct}\\s", "");
The .replaceAll("[^(-?\\d+(\\.\\d+)?)]", " ").trim() will replace everything within the String except for signed or unsigned Integer or floating point numerical values with a whitespace. It then trims the outcome of leading and or trailing whitespaces, tabs, etc (if any).
The .replaceAll("\\s\\p{Punct}|\\p{Punct}\\s", ""); will replace any remaining special characters like punctuation that contains a least one leading or one trailing whitespace. When the first replaceAll() above has completed there is most likely going to be straggling periods, etc remaining in the string. We don't want those for splitting the string so this replaceAll() will get rid of those stragglers.
All that should now remain in the string will be numerical values separated by one or more whitespaces. This is where the regex \\s+ used in the String#split() method comes in handy:
String[] numbers = parsable.split("\\s+");
This will split the new string based on one or more whitespaces. So, what is "90.7185 10 32" will be split into a String[] Array consisting of three elements, ["90.7185", "10", "32"]. Each element of this array is now converted to a double data type and added to the double type values[] Array.
public class ArrayIntro
{
public static void main(String[] args)
{
int[] a;
a=new int[10];
Scanner sc =new Scanner(System.in);
for(int i=0;i<10;i++)
{
a[i]=sc.nextInt();
}
for(int e:a)
{
System.out.print(e+' ');
}
}
}
Input:1 2 3 4 5 6 7 8 9 10
Output:33343536373839404142
Its mean it added 32 to each number
Just try with below code.
As you are printing sout inside for loop, it's printing sum of number and Space( ' '). And space have ASCII value of 32, so you are able to see every element with added value of 32.
For ASCII Or Unicode you can refer this link, it will help you.
Simply you put something like this System.out.print(new Integer(' '));, it will print 32.
If you want to add space only then go with double quote.
System.out.print(e+" ");.
Single quote consider as character and charater added with Integer will summing up with their ASCII code.
public static void main(String[] args)
{
int[] a;
a=new int[10];
Scanner sc =new Scanner(System.in);
for(int i=0;i<10;i++)
{
a[i]=sc.nextInt();
}
for(int e:a)
{
System.out.print(e+" ");
}
}
To put it simply, ' ' is a character in ASCII and the value of it is 32. So, as far as I know, you might want it the just print directly so you can just replace ' ' with " ". Always remember that single quotes are for characters and double quotes are for strings.
For your answer you can just do this:System.out.print(e+" ");
Instead of this: System.out.print(e+' ');
In short, to fix your program, you need to use " " (with double quotes) instead of ' '.
The issue is that the + operator has two different meanings in Java.
If either of the operands is a String, then + means "concatenate these two operands together". If the other operand is not a String, then it will have to be converted somehow, and there are some rules around how to do this.
If neither operand is a String, then + means "add these two operands together" - that is, they are treated as numbers. They can be added as double values, float values, long values or int values, depending on the data types. But if they are short, byte or char, they will be treated as int. This is called binary numeric promotion, and is explained in detail in the Java Language Specification.
Now in Java, single quotes are used to delimit a char literal. So when you write e + ' ', you're adding an int to a char. This is addition - the char is treated as an int, and the operands are added as numbers. The number corresponding to is 32, since that's the numeric value in the character encoding that Java uses, which is something like UTF-16. Contrary to some other answers on this page, it's not ASCII.
Double quotes are used to delimit a String literal. So if you write e + " ", the operands are an int and a String. That means you're not adding any more, but concatenating. The int is converted to a String first, then concatenated to " ", which will give you the result you're expecting.
Someone please help, How exactly can I take a string and break it up evenly.
for example (41-25) how can I pull the 41 or 25 out instead of getting a seperate 4 and 1.
Whenever I enter a double it registers it as each single digit including the period but not as a whole.
static double evaluate(String expr){
//Add code below
Stack<String> operators = new Stack<String>();
Stack<Double> values = new Stack<Double>();
String[] temp = expr.split("");
Double value = 0.0;
for(int i=0; i< temp.length;i++){
if(temp[i].equals("(")) continue;
else if(temp[i].equals("+")) operators.push(temp[i]);
else if(temp[i].equals("-")) operators.push(temp[i]);
else if(temp[i].equals("*")) operators.push(temp[i]);
else if(temp[i].equals("/")) operators.push(temp[i]);
else if(temp[i].equals(")")) {
String ops = operators.pop();
value = values.pop();
value = operate(values.pop(), value, ops);
System.out.println(value);
values.push(value);
}
else{
System.out.println(temp[i]);
Double current = Double.parseDouble(temp[i]);
values.push(current);
}
}
return 0;
}
I would split the string before and after any operator rather than splitting every character:
static double evaluate(String expr){
//Add code below
...
String[] temp = expr.split("((?<=[\+\-\*\/])|(?=[\+\-\*\/]))"); // Changes "41-25" to ["41", "-", "25"]
This uses regex to split the string using a positive look behind (?<=) and a positive lookahead (?=) with a character set inside for the four operators that you need [\+\-\*\/] (the operators are escaped with a backslash.
Any string will split before and after any operator. If you need more operators, they can be added to the character set.
With Java you could even make your character set a String to remove duplicate code by putting:
String operators = "\\+-\\*/";
String[] temp = expr.split("((?<=[" + operators + "])|(?=[" + operators + "]))";
This method enables you to change what operators to split on easily.
Life is very easy if the expression has values from 0 to 9 but
If expression = 23+52*5 is input by user then I take it in a String named expression.
Now what I want is that a new String or char Array in such a fashion that:
String s or char[] ch = ['23','+','52','*','5']
so that ch[0] or s.charAt(0) gives me 23 and not 2.
To do so I have tried the following and am stuck on what to do next:
for(int i=0;i<expression.length();i++)
{
int operand = 0;
while(i<expression.length() && sol.isOperand(expression.charAt(i))) {
// For a number with more than one digits, as we are scanning
// from left to right.
// Everytime , we get a digit towards right, we can
// multiply current total in operand by 10
// and add the new digit.
operand = (operand*10) + (expression.charAt(i) - '0');
i++;
}
// Finally, you will come out of while loop with i set to a non-numeric
// character or end of string decrement it because it will be
// incremented in increment section of loop once again.
// We do not want to skip the non-numeric character by
// incrementing it twice.
i--;
/**
* I have the desired integer value but how to put it on a string
* or char array to fulfill my needs as stated above.
**/
// help or ideas for code here to get desired output
}
In the while loop the method isOperand(char) is returning a boolean value true if char provided is >=0 or <=9.
You're going to want a String[] when you break the expression apart. Regex lookbehind/lookahead (Java Pattern Reference) allows you to split a String and keep the delimiters. In this case, your delimiters are the operands. You can use a split pattern like this:
public static void main(String[] args) throws Exception {
String expression = "23+52*5";
String[] pieces = expression.split("(?<=\\+|-|\\*|/)|(?=\\+|-|\\*|/)");
System.out.println(Arrays.toString(pieces));
}
Results:
[23, +, 52, *, 5]
One this to consider, is if your expression contains any spaces then you're going to want to remove them before splitting the expression apart. Otherwise, the spaces will be included in the results. To remove the spaces from the expression can be done with String.replaceAll() like this:
expression = expression.replaceAll("\\s+", "");
The "\\s+" is a regular expression pattern that means a whitespace character: [ \t\n\x0B\f\r]. This statement replaces all whitespace characters with an empty space essentially removing them.
String expr = "23+52*5";
String[] operands = expr.split("[^0-9]");
String[] operators = expr.split("[0-9]+");
This breaks it into:
try using a switch case:
//read first character
switch data
if number : what is it ( 0,1,2,3...?)
save the number
if its an operator
save operator
** 2 the switch has 4 cases for operators and 10 for digits **
// read the next character
again switch
if its a number after a number add both chars into a string
if its an operator "close" the number string and convert it into an int
If you will need some code I will gladly help.
Hope the answer is useful.
for i = 1 ; i = string.length
switch :
case 1,2,3,4,5,6,7,8,9,0 (if its a digit)
x(char) = char(i)
case +,-,*,/ (operator)
y(char) = char(i)
x[1] + x[2] +...x[n] = X(string) // build all the digits saves before the operator into 1 string
convert_to_int(X(string))
You can use regex:
\d+
Will grab any instance of one or more consecutive digits.
Let's say I have a time hh:mm (eg. 11:22) and I want to use a string tokenizer to split. However, after it's split I am able to get for example: 11 and next line 22. But how do I assign 11 to a variable name "hour" and another variable name "min"?
Also another question. How do I round up a number? Even if it's 2.1 I want it to round up to 3?
Have a look at Split a string using String.split()
Spmething like
String s[] = "11:22".split(":");;
String s1 = s[0];
String s2 = s[1];
And ceil for rounding up
Find ceiling value of a number using Math.ceil
Rounding a number up isn't too hard. First you need to determine whether it's a whole number or not, by comparing it cast as both an int and a double. If they don't match, the number is not whole, so you can add 1 to the int value to round it up.
// num is type double, but will work with floats too
if ((int)num != (double)num) {
int roundedNum = (int)num + 1;
}