Emilio
Emilio

Reputation: 89

Subtract more than two values using variadic

Hi guys I have the following class (it's a simple calculator). The subtract method accepts many parameter in input.

class Calculator {

    public function sum($a, $b)
    {
        return $a + $b; 
    }

    public function divide($a, $b)
    {
        return $a / $b;
    }

    public function subtract(int ...$b)
    {   
        for ($i = 0; $i < count($b) - 1; $i++)
        {
            $oldValue = $b[$i];
            $oldValue -= $b[$i+1];
        }
        return $oldValue;
    }

}

$calc = new Calculator();
var_dump($calc->subtract(13,4,5));

How can I subtract more than 2 numbers?? I cannot find the right solution for the right implementation of public function subtract(int ...$b) Someone could help me please?

Upvotes: 0

Views: 89

Answers (3)

Rinshan Kolayil
Rinshan Kolayil

Reputation: 1139

<?php

public function subtract(int ...$b)
{
    $num = $b[0]; // $num = 13;
    unset($b[0]); // $b = arrray(4,5)
    foreach ($b as $value) {
        $num -= $value;
    }
    return $num;
}

EDIT

unset will not reset index of the array where array_shift will reset the index of array, as per my previous experiments i am writing codes mostly without if conditions inside for loops whenever possible

unset O(1) Time complexity

array_shift O(n) Time complexity

BenchMarks

$max = 5000;
$times_a = [];
$times_b = [];
for ($i = 1; $i <= $max; $i += 1) {
    $start = microtime(TRUE);
    $array = range(0, 10000);
    array_shift($array);
    $end_time = microtime(TRUE);
    $times_a[] = $end_time - $start;
    //benchmark array lookups
    
    $start = microtime(TRUE);
    $array = range(0, 10000);
    unset($array[0]);
    $end_time = microtime(TRUE);
    $times_b[] = $end_time - $start;
}
$times = 0;
foreach ($times_a as $key => $value) {
    if($value > $times_b[$key]){ 
    //if time of array_shift greater than unset
        $times++;
    }
}
echo $times . '<br>'; //4953
echo count($times_a); //5000
// Unset is More usefull

If inside forloop

$max = 50000;
$times_a = [];
$times_b = [];
$start_time = microtime(TRUE);
for ($i = 1; $i <= $max; $i += 1) {
    $array = range(0, 10000);
    $oldValue = null;
    foreach($array as $num) {
        if(is_null($oldValue)) {
            $oldValue = $num;
        } else {
            $oldValue -= $num;
        }
    }
    $end_time = microtime(TRUE);
}
$end_time = microtime(TRUE);
echo $end_time - $start_time;
//17.108186006546

Unset First variable initially

$max = 50000;
$times_a = [];
$times_b = [];
$start_time = microtime(TRUE);
for ($i = 1; $i <= $max; $i += 1) {
    $array = range(0, 10000);
    $num = $array[0];
    unset($array[0]);
    foreach ($array as $value) {
        $num -= $value;
    }
    $end_time = microtime(TRUE);
}
$end_time = microtime(TRUE);

echo $end_time - $start_time;

//14.774175882339

Upvotes: 1

Don&#39;t Panic
Don&#39;t Panic

Reputation: 41820

Another way to do this is to shift the first number from the argument list, then subtract the sum of the remaining numbers.

public function subtract(int ...$b)
{
    $a = array_shift($b);
    return $a - array_sum($b);
}

It could also be simplified by modifying the function signature to accept a beginning number as well as a variable-length list of numbers to subtract from it.

public function subtract(int $a, int ...$b)
{
    return $a - array_sum($b);
}

Upvotes: 0

aynber
aynber

Reputation: 23001

At the moment you're resetting $oldValue each time, when you really need to set it in the beginning and go from there.

public function subtract(int ...$b)
{
    $oldValue = null;
    foreach($b as $num) {
        if(is_null($oldValue)) {
            $oldValue = $num;
        } else {
            $oldValue -= $num;
        }
    }
    return $oldValue;
}

Upvotes: 0

Related Questions