How to Make a Calculator in PHP

How to make PHP Calculator Store and Display History

To work with sessions, first of all you may start any PHP script using $_SESSION with session_start():

<?php

session_start();

Then you can initialize an array result storage with:

if (!isset($_SESSION['results'])){
$_SESSION["results"] = [];
}

And add stored values using :

$_SESSION["results"][]="New result";

For example, you can store the operation result after calculation, like here:

if ($operation == '+') {
$Result = ((int)$numberOne + (int)$numberTwo);
$_SESSION["results"][]="$numberOne + $numberTwo = $Result";
}

You may use any string/number/array values to store the result in a more structured way if you want. Then you can add your saved results to the HTML form page (must be a .php file, not .html), for example:

<div class="logs">
<?php echo implode("<br>",$_SESSION["results"]); ?>
</div>

To clean/reset the results array, you can add a new 'reset' operation or something like this to do that:

if ($operation == 'reset'){
$_SESSION["results"] = [];
}

How to make a calculator in PHP?

Depending on your needs, I would suggest looking into the Shunting Yard Algorithm. It's pretty easy to implement, and works quite well.

Here's an example I whipped up a while ago: GIST.

Here's the code copy/pasted into one block:

Expression Definitions:

class Parenthesis extends TerminalExpression {

protected $precidence = 7;

public function operate(Stack $stack) {
}

public function getPrecidence() {
return $this->precidence;
}

public function isNoOp() {
return true;
}

public function isParenthesis() {
return true;
}

public function isOpen() {
return $this->value == '(';
}

}

class Number extends TerminalExpression {

public function operate(Stack $stack) {
return $this->value;
}

}

abstract class Operator extends TerminalExpression {

protected $precidence = 0;
protected $leftAssoc = true;

public function getPrecidence() {
return $this->precidence;
}

public function isLeftAssoc() {
return $this->leftAssoc;
}

public function isOperator() {
return true;
}

}

class Addition extends Operator {

protected $precidence = 4;

public function operate(Stack $stack) {
return $stack->pop()->operate($stack) + $stack->pop()->operate($stack);
}

}

class Subtraction extends Operator {

protected $precidence = 4;

public function operate(Stack $stack) {
$left = $stack->pop()->operate($stack);
$right = $stack->pop()->operate($stack);
return $right - $left;
}

}

class Multiplication extends Operator {

protected $precidence = 5;

public function operate(Stack $stack) {
return $stack->pop()->operate($stack) * $stack->pop()->operate($stack);
}

}

class Division extends Operator {

protected $precidence = 5;

public function operate(Stack $stack) {
$left = $stack->pop()->operate($stack);
$right = $stack->pop()->operate($stack);
return $right / $left;
}

}

class Power extends Operator {

protected $precidence=6;

public function operate(Stack $stack) {
$left = $stack->pop()->operate($stack);
$right = $stack->pop()->operate($stack);
return pow($right, $left);
}
}

abstract class TerminalExpression {

protected $value = '';

public function __construct($value) {
$this->value = $value;
}

public static function factory($value) {
if (is_object($value) && $value instanceof TerminalExpression) {
return $value;
} elseif (is_numeric($value)) {
return new Number($value);
} elseif ($value == '+') {
return new Addition($value);
} elseif ($value == '-') {
return new Subtraction($value);
} elseif ($value == '*') {
return new Multiplication($value);
} elseif ($value == '/') {
return new Division($value);
} elseif ($value == '^') {
return new Power($value);
} elseif (in_array($value, array('(', ')'))) {
return new Parenthesis($value);
}
throw new Exception('Undefined Value ' . $value);
}

abstract public function operate(Stack $stack);

public function isOperator() {
return false;
}

public function isParenthesis() {
return false;
}

public function isNoOp() {
return false;
}

public function render() {
return $this->value;
}
}

The stack (really simple implementation):

class Stack {

protected $data = array();

public function push($element) {
$this->data[] = $element;
}

public function poke() {
return end($this->data);
}

public function pop() {
return array_pop($this->data);
}

}

And finally, the executor class:

class Math {

protected $variables = array();

public function evaluate($string) {
$stack = $this->parse($string);
return $this->run($stack);
}

public function parse($string) {
$tokens = $this->tokenize($string);
$output = new Stack();
$operators = new Stack();
foreach ($tokens as $token) {
$token = $this->extractVariables($token);
$expression = TerminalExpression::factory($token);
if ($expression->isOperator()) {
$this->parseOperator($expression, $output, $operators);
} elseif ($expression->isParenthesis()) {
$this->parseParenthesis($expression, $output, $operators);
} else {
$output->push($expression);
}
}
while (($op = $operators->pop())) {
if ($op->isParenthesis()) {
throw new RuntimeException('Mismatched Parenthesis');
}
$output->push($op);
}
return $output;
}

public function registerVariable($name, $value) {
$this->variables[$name] = $value;
}

public function run(Stack $stack) {
while (($operator = $stack->pop()) && $operator->isOperator()) {
$value = $operator->operate($stack);
if (!is_null($value)) {
$stack->push(TerminalExpression::factory($value));
}
}
return $operator ? $operator->render() : $this->render($stack);
}

protected function extractVariables($token) {
if ($token[0] == '$') {
$key = substr($token, 1);
return isset($this->variables[$key]) ? $this->variables[$key] : 0;
}
return $token;
}

protected function render(Stack $stack) {
$output = '';
while (($el = $stack->pop())) {
$output .= $el->render();
}
if ($output) {
return $output;
}
throw new RuntimeException('Could not render output');
}

protected function parseParenthesis(TerminalExpression $expression, Stack $output, Stack $operators) {
if ($expression->isOpen()) {
$operators->push($expression);
} else {
$clean = false;
while (($end = $operators->pop())) {
if ($end->isParenthesis()) {
$clean = true;
break;
} else {
$output->push($end);
}
}
if (!$clean) {
throw new RuntimeException('Mismatched Parenthesis');
}
}
}

protected function parseOperator(TerminalExpression $expression, Stack $output, Stack $operators) {
$end = $operators->poke();
if (!$end) {
$operators->push($expression);
} elseif ($end->isOperator()) {
do {
if ($expression->isLeftAssoc() && $expression->getPrecidence() <= $end->getPrecidence()) {
$output->push($operators->pop());
} elseif (!$expression->isLeftAssoc() && $expression->getPrecidence() < $end->getPrecidence()) {
$output->push($operators->pop());
} else {
break;
}
} while (($end = $operators->poke()) && $end->isOperator());
$operators->push($expression);
} else {
$operators->push($expression);
}
}

protected function tokenize($string) {
$parts = preg_split('((\d+|\+|-|\(|\)|\*|/)|\s+)', $string, null, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
$parts = array_map('trim', $parts);
return $parts;
}

}

It works by first tokenizing the input (based on word boundary, and tokens). Then, it runs the Shunting Yard algorithm on it to convert the input into a RPN (Reverse Polish Notation) stack. Then, it's just a matter of executing the stack. Here's a quick example:

$math = new Math();

$answer = $math->evaluate('(2 + 3) * 4');
var_dump($answer);
// int(20)

$answer = $math->evaluate('1 + 2 * ((3 + 4) * 5 + 6)');
var_dump($answer);
// int(83)

$answer = $math->evaluate('(1 + 2) * (3 + 4) * (5 + 6)');
var_dump($answer);
// int(231)

$math->registerVariable('a', 4);
$answer = $math->evaluate('($a + 3) * 4');
var_dump($answer);
// int(28)

$math->registerVariable('a', 5);
$answer = $math->evaluate('($a + $a) * 4');
var_dump($answer);
// int(40)

Now, this example is significantly more complex than you may need. The reason is that it also handles grouping and operator precedence. But it's a decent example of a running algorithm that doesn't use EVAL and supports variables...

How to make a PHP calculator with 3 variables

your code is not that bad for a beginner, but it still needs some work. Why would you use multiple functions doing more or less the same calculation? You are a ware, that you can call any function multiple time?

Then, check your code. You have a lot of variable mistakes, as you name them different.

Also your variable naming is not so well readable. Give the variables names, so you know what they are supposed to be. On this small code level, this is not that big of a deal. If you work with a lot of code, a good naming can make up a lot!

If you plan to stay on to programming, you want to train yourself to check those issues early. This will save you a lot of time in the future, as you will be trained to do this automatically.

I have more or less corrected your code. I have written some comments to hint out parts and fixes, so you understand what has changed and why.

If you get grades for this calculator project, keep in mind there is still a lot of stuff you can do better. At least if you want to get the best grade.

  • Check your naming.

  • Address security issues. (If anyone sees you do this as a beginner,they will be impressed!)

  • Commenting your code. You have comments, but they are not enough. Comment anything possible so people understand what the code is doing just by reading the comment.

Some corrected code:

<?php
// you only need one function. why would you need a lot of functions doing the same?
function calculate($x, $y, $op) {
// calculate $prod using switch (case) statement
switch($op) {
case '+':
$prod = $x + $y;
break;
case '-':
$prod = $x - $y;
break;
case '*':
$prod = $x * $y;
break;
case '/':
if ($y == 0) {$prod = "∞";}
else {$prod = $x / $y;}
break;
}

// do return your result AFTER the switch. else you will not get any results in most cases
return $prod;
}

// you can do this, but keep in mind, this is more or less a security issue!
// you may want to check how to work with $_GET variables. as it is for school work, it is not critical yet,
// but if you plan to use php in future you may want to have a look at some ways to avoid problems.
extract($_GET);

// in this example is no need to predefine the variables as you had it, as wich each post the value get lost and it only uses the information from $_GET

?>
<html>

<head>
<title>PHP Calculator Version 2.12</title>
</head>

<body>

<h3>PHP Calculator (Version 2.12)</h3>

<form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">

x = <input type="text" name="x" size="5" value="<?php print $x; ?>" /> op1 =
<select name="op1">
<option value="+" <?php if ($op1=='+') echo 'selected="selected"';?>>+</option>
<option value="-" <?php if ($op1=='-') echo 'selected="selected"';?>>-</option>
<option value="*" <?php if ($op1=='*') echo 'selected="selected"';?>>*</option>
<option value="/" <?php if ($op1=='/') echo 'selected="selected"';?>>/</option>
</select> y = <input type="text" name="y" size="5" value="<?php print $y; ?>" /> op2 =
<select name="op2">
<option value="+" <?php if ($op2=='+') echo 'selected="selected"';?>>+</option>
<option value="-" <?php if ($op2=='-') echo 'selected="selected"';?>>-</option>
<option value="*" <?php if ($op2=='*') echo 'selected="selected"';?>>*</option>
<option value="/" <?php if ($op2=='/') echo 'selected="selected"';?>>/</option>
</select> z = <input type="text" name="z" size="5" value="<?php print $z; ?>" />
<input type="submit" name="calc" value="Calculate" />
</form>

<?php
if(isset($calc)) {
if (is_numeric($x) && is_numeric($y) && is_numeric($z)) {
// if you use OR / AND or any other operator, make sure both sides have a counterpart to work with.
if ($op1 == '*' or $op1 == '/') {
// you can use the same function multiple times as seen below
$prod1 = calculate($x, $y, $op1);
$prod2 = calculate($prod1, $z, $op2);
}
else if ($op2 == '*' or $op2 == '/') {
$prod1 = calculate($y, $z, $op2);
$prod2 = calculate($x, $prod1, $op1);
}
else {
$prod1 = calculate($x, $y, $op1);
$prod2 = calculate($prod1, $z, $op2);
}

// make sure what you print does also exist!
echo "<p>$x $op1 $y $op2 $z = $prod2 </p>";
}
else {
// unaccepatable values
echo "<p>x, y, and z values are required to be numeric ...
please re-enter values</p>";
}
}
?>
</body>
</html>

Only PHP Code Calculator with Clickable Buttons as Input

This is my truly basic, almost style-less, pure-PHP calculator form:

<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Basic PHP Calculator</title>
</head>
<body>
<?php
//var_export($_POST);
//echo "<br>";
$buttons = [1,2,3,'+',4,5,6,'-',7,8,9,'*','C',0,'.','/','='];
$pressed = '';
if (isset($_POST['pressed']) && in_array($_POST['pressed'], $buttons)) {
$pressed = $_POST['pressed'];
}
$stored = '';
if (isset($_POST['stored']) && preg_match('~^(?:[\d.]+[*/+-]?)+$~', $_POST['stored'], $out)) {
$stored = $out[0];
}
$display = $stored . $pressed;
//echo "$pressed & $stored & $display<br>";
if ($pressed == 'C') {
$display = '';
} elseif ($pressed == '=' && preg_match('~^\d*\.?\d+(?:[*/+-]\d*\.?\d+)*$~', $stored)) {
$display .= eval("return $stored;");
}

echo "<form action=\"\" method=\"POST\">";
echo "<table style=\"width:300px;border:solid thick black;\">";
echo "<tr>";
echo "<td colspan=\"4\">$display</td>";
echo "</tr>";
foreach (array_chunk($buttons, 4) as $chunk) {
echo "<tr>";
foreach ($chunk as $button) {
echo "<td",(count($chunk) != 4 ? " colspan=\"4\"" : "") , "><button name=\"pressed\" value=\"$button\">$button</button></td>";
}
echo "</tr>";
}
echo "</table>";
echo "<input type=\"hidden\" name=\"stored\" value=\"$display\">";
echo "</form>";
?>
</body>
</html>

Here is a screenshot while I was testing:

Sample Image

You can see that I've made every button a submit button with the same name, but different values. I use a single hidden input to preserve built expression. There will be many enhancements and considerations beyond this demo, it is up to you how far to go down this rabbit hole.


P.S. For anyone who just unholstered their sidearm, squinted one eye, and sternly uttered "Hey, we don't take kindly to folks like you callin' eval() in these here parts!". Well, I've endeavored to adequately validate the string to be evaluated. If there is a known hole, please let me know and I'll try to fix it. Alternatively, this is my attempt to re-invent the eval() process with BOMDAS in mind:

Code: (Demo)

$stored = "2+3*4/6";
$components = preg_split('~([*/+-])~', $stored, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
while (($index = array_search('*', $components)) !== false) {
array_splice($components, $index - 1, 3, $components[$index - 1] * $components[$index + 1]);
}
while (($index = array_search('/', $components)) !== false) {
array_splice($components, $index - 1, 3, $components[$index - 1] / $components[$index + 1]);
}
while (($index = array_search('+', $components)) !== false) {
array_splice($components, $index - 1, 3, $components[$index - 1] + $components[$index + 1]);
}
while (($index = array_search('-', $components)) !== false) {
array_splice($components, $index - 1, 3, $components[$index - 1] - $components[$index + 1]);
}
echo current($components); // 4

Calculator using switch case in PHP

You have lot of bugs in your code. like

1) You have declared function but never call it.

2) Variable names issue.

3) Submit button value and switch case never match etc...

You need to change your code as below:

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Untitled Document</title>
<?php
$num1 = "";
$num2 = "";
$calc = "";

if (isset($_POST['submit']))
{

$num1 = $_POST['n1'];
$num2 = $_POST['n2'];

function calculate($num1,$num2){
$calc = "";
switch ($_POST['submit']) {

case 'addition':
$calc = $num1 + $num2;
break;

case 'sub':
$calc = $num1 - $num2;
break;
}
return $calc;
}
$calc = calculate($num1,$num2);
}
?>
</head>

<body>

<form action="" method="post">
NO 1 : <input name='n1' value="<?php echo $num1;?>">
<br><br>
NO 2: <input name='n2' value="<?php echo $num2?>"><br><br>
total: <input type="res" value="<?php echo $calc;?>"><br><br>
<input type="submit" name="submit" value="addition">
<input type="submit" name="submit" value="sub">

</form>
</body>
</html>

php basic calculator with function and switch but result is

Here is complete code:

<?php
$num1 = $_POST['num1'];
$num2 = $_POST['num2'];
$calcu = $_POST['calcu'];

function calculate($n1,$n2, $calcu) // set $calcu as parameter
{
switch($calcu)
{
case "Addition": // here you have to use colons not semi-colons
$compute = $n1 + $n2;
break;
case "Subtraction":
$compute = $n1 - $n2;
break;
case "Multiplication":
$compute = $n1 * $n2;
break;
case "Division":
$compute = $n1 / $n2;
break;
}
return $compute; // returning variable
}
echo "$calcu <br /> <br /> 1st Number: $num1 <br /> 2nd Number: $num2 <br /><br />";
echo "Answer is:" .calculate($num1,$num2, $calcu); // you need to pass $calcu as argument of that function
?>


Related Topics



Leave a reply



Submit