0

I wrote this:

$num1 = mt_rand(1,5);
$num2 = mt_rand(1,5);

$operators = array(
    "+",
    "-",
    "*",
    "/" 
    );

$result = $num1 . $operators[array_rand($operators)] . $num2;

(My best guess is) This doesn't work as I expected because in the array the operator is a string which makes everything a string:

var_dump($result);

Gives:

string(3) "4+3"

So my question would be how would you recommend approaching this* without changing the logic it too much?

Thanks in advance!!


*Making random operation among random numbers, and if possible, the operators should be stored in an array.


I have the feeling my title is not correctly describing the situation but I could not come up with a better idea, I'm open to suggestions :)

4 Answers 4

3

Of course, you could use eval to do this, but I certainly won't settle for such a solution.

I'd suggest defining a bunch of functions that take in two params and return a result, then use call_user_func_array on the result of array_rand.

function add($x, $y) { return $x + $y; }
function subtract($x, $y) { return $x - $y; }
function multiply($x, $y) { return $x * $y; }
function divide($x, $y) { return $x / $y; }

$operators = array('add', 'subtract', 'multiply', 'divide');
//...
$result = call_user_func_array($operators[array_rand($operators)], array($x, $y)); 
Sign up to request clarification or add additional context in comments.

2 Comments

thanks! that looks real good!! for some reason, I'm just not convinced yet with the switch answers.
@Akinator, Indeed. I try to avoid using the switch statement.
2
<?php

$num1 = mt_rand(1, 5);
$num2 = mt_rand(1, 5);

$operators = array(
    "+",
    "-",
    "*",
    "/"
);

switch ($operators[array_rand($operators)]) {
    case "+":
        $result = $num1 + $num2;
        break;
    case "-":
        $result = $num1 - $num2;
        break;
    case "*":
        $result = $num1 * $num2;
        break;
    case "/":
        $result = $num1 / $num2;
        break;
}

var_dump($result);

2 Comments

Ok, I sort of like it (specially since it actually solves the problem) but isn't it kind of redundant?
@Akinator No, switch is not redundant.
2

The clean solution would be to have a code branch for each operator, e.g.

function do_something($num1, $num2, $operator) {
  switch ($operator) {
    case '+':
      return $num1 + $num2;
    case '-':
      return $num1 - $num2;
    case '*':
      return $num1 * $num2;
    case '/':
      return $num1 / $num2;
    default:
      throw new Exception('Unknown operator: '.$operator)
  }
}

If you have more operators, you should create a map of operator => function and dynamically call the functions, for example:

$ftable = array(
  '+' => 'fn_add',
  '-' => 'fn_sub',
  '*' => 'fn_mul',
  '/' => 'fn_div'
);

function fn_add($a, $b) { return $a + $b; }
function fn_sub($a, $b) { return $a - $b; }
function fn_mul($a, $b) { return $a * $b; }
function fn_div($a, $b) { return $a / $b; }

function do_something($num1, $num2, $operator) {
  global $ftable;
  if (array_key_exists($operator, $ftable)) {
    return call_user_func($ftable[$operator], $num1, $num2);
  }
  else {
    throw new Exception('Unknown operator: '.$operator)
  }
}

And of course, the unclean (slow, potentially dangerous) solution would be to use eval().

4 Comments

eval() is evil(). Ok I don't know why I'm not sure about that (Of course it actually solves the problem so thanks) but I'll see where it goes.
You're absolutely correct, eval() is evil. Thus I recommend against using it. :)
I extended my answer with a dispatch map example. You could also use '+' => create_function(...) or, in new PHP versions, '+' => function($a,$b){ return $a+$b; }. And you should use classes and not globals... :)
very compete answer +1, I'm not actually accepting it because I feel @Jacob 's answer answer is a little bit cleaner, but specially is more "in my line of though" (absolutely subjective) but thanks again for great answer!
0

Create a function for each operation, then store operator => function name in an array.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.