views:

120

answers:

1

I've wrote a parser in PHP that converts a string representation of an equation to RPN based on feedback from an earlier question. Whilst testing it I found two different equations that parse to the same thing in RPN. Because they end up as the same thing in RPN when you solve them you get the same answer.

  1. 3 + 4 * 8 / (1 -5)
  2. 3 + 4 * 8 / 1 -5

Both end up as 348*15-/+ which when solved gives an answer of -5 which is correct for the first one, but the answer to the second one should be 30.

So have I misunderstood how to convert to RPN? The code to my parser can be found in the above link to the previous question.

+1  A: 

I found the error in your parser. In your last big else block, you need to replace

$current = end($stack);
if($operators[$tokens[$i]] == $operators[$current]) {
  $rpn .= array_pop($stack);
  $stack[] = $tokens[$i];
} else {
  $stack[] = $tokens[$i];
}

with

while(!empty($stack) && end($stack) != '(' && $operators[$tokens[$i]] >= $operators[end($stack)]) {
  $rpn .= array_pop($stack);
}
$stack[] = $tokens[$i];

After that change, your two test cases work fine here. (I used this reference to fix your code. I stopped checking your code after fixing the problem in your question, so there might be more bugs inside -- I did not proof-read everything!)

EDIT: The important thing is replacing "==" with ">=". If you will always have only two levels of precedence, replacing the if with a loop is not strictly necessary.

Heinzi
After looking at your link I saw my error, I thought you only popped the last operator off the stack, didn't realise you keep popping operators until the next one is lower in precedence.
RMcLeod
That's not the thing that broke your example, however: The important difference is that you only popped ops with the *same* precedence (==), although you need to pop *same precedence and higher* (>=).
Heinzi