How to add random operator from array in PHP

2019-06-09 05:51发布

问题:

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 :)

回答1:

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)); 


回答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);


回答3:

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:

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