PHP: How to select maximum probability value randomly? - php

I have below array & code
$a = [
149 => 55,
130 => 10,
131 => 5,
132 => 5,
133 => 10,
134 => 10,
135 => 5
];
$rand = rand (0,(count($a)-1));
echo array_values($a)[$rand];
This will give majorly result as 5,10 instead of 55.
Total of value is 100% probability. Values can be in decimal as well like 55.55, 10.10, etc. but overall going to be 100%
I already followed https://www.geeksforgeeks.org/how-to-get-random-value-out-of-an-array-in-php/
But this is not giving perfect result as expected.
So which has highest probability should be selected majorly and randomly.
So result can be like this : 55, 55, 10, 10, 10, 55, 5, etc..
I found some useful link Generating random results by weight in PHP? where Probability = Weight

Right now, your array is this: -
55, 10, 5, 5, 10, 10, 5
Now, you should generate a random number between [0, 100), let's call it r.
Now, if r lies between [0, 55), select the value 55.
else if r lies between [55, 55 + 10 = 65), select the value 10.
else if r lies between [65, 65 + 5 = 70), select the value 5.
else if r lies between [70, 70 + 5 = 75), select the value 5.
else if r lies between [75, 75 + 10 = 85), select the value 10.
else if r lies between [85, 85 + 10 = 95), select the value 10.
else if r lies between [95, 95 + 5 = 100), select the value 5.
I am sure you would have got the idea...
So, for the general case, if you have an array named 'arr', this is the pseudocode: -
function SELECTPROB()
{
$r = generateRandomNumber(0, 100); //function to generate random number between 0 and 100, (100 exclusive)
$sum = 0;
foreach($arr as $i)
{
if($r >= $sum && $r < $sum + $i)
{
return $i
}
$sum = $sum + $i
}
return -1 //Should technically never reach upto this, but it can if your probability's sum is not 100
}

Here is an implementation similar to roulette wheel selection in GA.
a version of the answer by EReload but bounded to the sum rather than a 100.
$a = [
149 => 55,
130 => 10,
131 => 5,
132 => 5,
133 => 10,
134 => 10,
135 => 5
];
echo randSelect($a);
function randSelect($a) {
$values = array_values($a);
$sum = array_sum($values);
$rand = (rand(0,1000)/1000) * $sum;
$partialSum = 0;
for ($i=0; $i < count($values); $i++) {
$partialSum += $values[$i];
if($partialSum >= $rand){
return $values[$i];
// incase you are using something like array_count_values and are actually looking for the keys
// return array_keys($a)[$i];
}
}
}

As i understand, you want higher number appear more frequently in rand method no matter how many times smaller number appear in your array. You need unique your array first.
Random by sum weight is simple method for random, but you can control weight more freely by sum power instead of itself.
$a = [
149 => 55,
130 => 10,
131 => 5,
132 => 5,
133 => 10,
134 => 10,
135 => 5
];
$val_arr = array_unique(array_values($a));
function rand_by_sum($arr, $power=1){
$sum = 0;
$f_val = function($f)use($power){
return pow($f, $power);
};
foreach($arr as $f){
$sum += $f_val($f);
}
$rand = mt_rand(0, $sum);
$tmp_sum = 0;
foreach($arr as $f){
$tmp_sum += $f_val($f);
if($tmp_sum >= $rand) return $f;
}
}
for($i=0; $i< 10; $i++){
echo rand_by_sum($val_arr, $argv[1]) . " ";
}
echo "\n";
And here some test result with different pow
php test.php 0.5
55 5 10 55 5 55 55 5 55 55
php test.php 2
55 55 10 55 55 55 55 55 55 55
php test.php 1
55 10 55 55 55 55 55 55 55 10
To get value, you revert array as 55 => [149] then get result from random, and random again in values of reverted array

Looking for answer which works in all scenarios or for any number.
and
Values can be in decimal as well like 55.55, 10.10, etc. but overall going to be 100%
Although you are limiting the total weight to 100, the fact that you want to accommodate decimal values in that range means that you cannot assume a maximum of 100 units to pick from. If you have a granularity of tenths, then each unit to potentially pick from will be .1 . If specifying down to hundredths (like 55.55) then you will need a relative base unit of .01 at a time.
Because I'd prefer not to iterate by float values, I recommend that you scale up all of your values by a factor that eliminates all floats in the weight and the random number generator -- simply multiply by 10/100/1000 whatever you need to convert all of the weights into integers.
Now to make the shortest work of the iteration process:
Loop through your input array once to establish the longest decimal precision.
Pick a random integer between 0 and ((the sum of all weights minus 1) multiplied by 10 to the power of "the longest representing decimal length").
Loop through your input array again and simply check if the random integer is less than the current weight plus any previous weight(s); if not if so, break the loop and because the selected weighted, random number has been located.
Code: (Demo) -- the demo makes 10 iterations to aid in revealing the weighted effect
$valueWeights = [
149 => 55.555,
130 => 10.0050,
131 => 5,
132 => 5.2,
133 => 10,
134 => 10.24,
135 => 5
];
$mostDecimals = 0;
// not bothering to validate against infinite and extremely fringe case floats
foreach ($valueWeights as $value => $weight) {
$tempDecimals = 0;
while ((string)$weight !== (string)floor($weight)) {
$weight *= 10; // this is not permanently mutating the weight
++$tempDecimals;
}
$mostDecimals = max($mostDecimals, $tempDecimals);
}
echo "Most Decimals: {$mostDecimals}\n";
$factor = pow(10, $mostDecimals);
echo "Factor: " , $factor , "\n";
$totalWeight = (array_sum($valueWeights) - 1) * $factor;
for ($i = 0; $i < 10; ++$i) {
$rand = mt_rand(0, $totalWeight);
echo "\nRand: " , $rand , "\n";
$cumulativeScaledWeight = 0;
foreach ($valueWeights as $value => $weight) {
$cumulativeScaledWeight += $weight * $factor;
if ($rand < $cumulativeScaledWeight) {
echo "Value: {$value}\n";
break;
}
}
}
Output:
Most Decimals: 3
Factor: 1000
Rand: 52197
Value: 149
Rand: 33785
Value: 149
Rand: 4783
Value: 149
Rand: 24994
Value: 149
Rand: 76588
Value: 133
Rand: 77417
Value: 133
Rand: 40541
Value: 149
Rand: 80009
Value: 133
Rand: 14826
Value: 149
Rand: 52691
Value: 149

I think you could actually shuffle the array and pop an element, shuffle again and pop the element, that would be randomly and those numbers with greater probability would be first.
What you can do is to create another array with 100 numbers, representing the total probability and inserting in it the amount of numbers equal to its value, finally you shuffle it to pick an index random later. Then you will get an array of 100 numbers where there most repeated number is the most probable. Lastly you just have to pick a random index and create your array.
can you tell me if you are looking for something like this or if I am misunderstanding the problem
function getProb($array, $elements)
{
$myNewArray = [];
$myProbabilisticArray = $this->getProbabilisticArray($array);
for ($i=0; $i < $elements; $i++) {
$myNewArray[] = $myProbabilisticArray[array_rand($myProbabilisticArray)];
}
return $myNewArray;
}
function getProbabilisticArray($array) {
$myNewArray = [];
rsort($array);
$currentProbability = 0;
$accumulatedProbability = $array[0];
$currentPosition = 0;
while ($currentProbability < 100) {
if ($currentProbability > $accumulatedProbability) {
$currentPosition++;
$accumulatedProbability += $array[$currentPosition];
}
array_push($myNewArray, $array[$currentPosition]);
$currentProbability++;
}
shuffle($myNewArray);
return $myNewArray;
}

Related

Check in what range is a number

I have a random number from 0 to 100 (x) and different ranges. How to check in which range the number is?
Example:
Given
Case1 (0 - 40),
Case2 (40 - 60),
Case3 (60 - 75),
Case4 (75 - 85),
Case5 (85 - 100)
and x = 50, the result should be Case2.
Here's one example on how to check which range a given number belongs to. Define an associative ranges array, where cases are keys and bottom limits are key values. Then loop the array through and compare the given number to the limits. If the number equals or is bigger than the limit, return the limit's case.
$range = in_which_range( rand(0,100) );
function in_which_range( int $number ) {
foreach ( ranges() as $case => $bottom_limit ) {
if ( $number >= $bottom_limit ) {
return $case;
}
}
}
function ranges() {
return array(
'case5' => 85,
'case4' => 75,
'case3' => 60,
'case2' => 40,
'case1' => 0,
);
}
So, you have 5 ranges:
Range #0: 0-40
Range #1: 41-60 (note that this range starts from 41, not from 40; otherwise you will get intersecting ranges that's probably not what you originally wanted)
Range #2: 61-75
Range #3: 76-85
Range #4: 86-100
You can store your ranges in a single array, just put there all range borders sorted.
$ranges = [0, 40, 60, 75, 85, 100];
Note that you have 5 ranges, but 6 elements in array - that's important. Now you can easily check for each range:
$findRange = function(int $x, int ...$ranges): ?int
{
for ($i = 0; $i < count($ranges) - 1; $i++) {
$start = 0 == $i ? $ranges[$i] : $ranges[$i] + 1;
$end = $ranges[$i + 1];
if ($x >= $start && $x <= $end) {
return $i;
}
}
return null;
};
foreach ([0, 41, 86, 101] as $x) {
$range = $findRange($x, ...$ranges);
$message = null === $range
? "Value {$x} is not in the range"
: "Value {$x} is in range #{$range}";
echo $message, PHP_EOL;
}
This will output:
Value 0 is in range #0
Value 41 is in range #1
Value 86 is in range #4
Value 101 is not in the range
Here is the working demo.

Make an output of 1 2 4 8 11 12 14 18... using one for loop

How can I generate a sequence of numbers like
1 2 4 8 11 12 14 18 ...
(plus 10 every 4 numbers) with the following additional requirements:
using only one loop
output should stop when a value in the sequence is greater than a specified input
Examples
$input = 24;
1 2 4 8 11 12 14 18 21 22 24
$input = 20;
1 2 4 8 11 12 14 18
Here's what I tried so far:
<?php
// sample user input
$input = 20;
$number = 1;
$counter = 0;
$array = array();
//conditions
while ($counter < 4) {
$counter++;
array_push($array, $number);
$number += $number;
}
//outputs
for ($x = 0; $x < count($array); $x++) {
echo $array[$x];
echo " ";
}
Code: (Demo)
function arrayBuilder($max,$num=1){
$array=[];
for($i=0; ($val=($num<<$i%4)+10*floor($i/4))<=$max; ++$i){
$array[]=$val;
}
return $array;
}
echo implode(',',arrayBuilder(28)),"\n"; // 1,2,4,8,11,12,14,18,21,22,24,28
echo implode(',',arrayBuilder(28,2)),"\n"; // 2,4,8,16,12,14,18,26,22,24,28
echo implode(',',arrayBuilder(20)),"\n"; // 1,2,4,8,11,12,14,18
echo implode(',',arrayBuilder(24)),"\n"; // 1,2,4,8,11,12,14,18,21,22,24
This method is very similar to localheinz's answer, but uses a technique introduced to me by beetlejuice which is faster and php version safe. I only read localheinz's answer just before posting; this is a matter of nearly identical intellectual convergence. I am merely satisfying the brief with the best methods that I can think of.
How/Why does this work without a lookup array or if statements?
When you call arrayBuilder(), you must send a $max value (representing the highest possible value in the returned array) and optionally, you can nominate $num (the first number in the returned array) otherwise the default value is 1.
Inside arrayBuilder(), $array is declared as an empty array. This is important if the user's input value(s) do not permit a single iteration in the for loop. This line of code is essential for good coding practices to ensure that under no circumstances should a Notice/Warning/Error occur.
A for loop is the most complex loop in php (so says the manual), and its three expressions are the perfect way to package the techniques that I use.
The first expression $i=0; is something that php developers see all of the time. It is a one-time declaration of $i equalling 0 which only occurs before the first iteration.
The second expression is the only tricky/magical aspect of my entire code block. This expression is called before every iteration. I'll try to break it down: (parentheses are vital to this expression to avoid unintended results due to operator precedence
( open parenthesis to contain leftside of comparison operator
$val= declare $val for use inside loop on each iteration
($num<<$i%4) because of precedence this is the same as $num<<($i%4) meaning: "find the remainder of $i divided by 4 then use the bitwise "shift left" operator to "multiply $num by 2 for every "remainder". This is a very fast way of achieving the 4-number pattern of [don't double],[double once],[double twice],[double three times] to create: 1,2,4,8, 2,4,8,16, and so on. bitwise operators are always more efficient than arithmetic operators.The use of the arithmetic operator modulo ensure that the intended core number pattern repeats every four iterations.
+ add (not concatenation in case there is any confusion)
10*floor($i/4) round down $i divided by 4 then multiply by 10 so that the first four iterations get a bonus of 0, the next four get 10, the next four get 20, and so on.
) closing parenthesis to contain leftside of comparison operator
<=$max allow iteration until the $max value is exceeded.
++$i is pre-incrementing $i at the end of every iteration.
Complex solution using while loop:
$input = 33;
$result = [1]; // result array
$k = 0; // coeficient
$n = 1;
while ($n < $input) {
$size = count($result); // current array size
if ($size < 4) { // filling 1st 4 values (i.e. 1, 2, 4, 8)
$n += $n;
$result[] = $n;
}
if ($size % 4 == 0) { // determining each 4-values sequence
$multiplier = 10 * ++$k;
}
if ($size >= 4) {
$n = $multiplier + $result[$size - (4 * $k)];
if ($n >= $input) {
break;
}
$result[] = $n;
}
}
print_r($result);
The output:
Array
(
[0] => 1
[1] => 2
[2] => 4
[3] => 8
[4] => 11
[5] => 12
[6] => 14
[7] => 18
[8] => 21
[9] => 22
[10] => 24
[11] => 28
[12] => 31
[13] => 32
)
On closer inspection, each value in the sequence of values you desire can be calculated by adding the corresponding values of two sequences.
Sequence A
0 0 0 0 10 10 10 10 20 20 20 20
Sequence B
1 2 4 8 1 2 4 8 1 2 4 8
Total
1 2 4 8 11 12 14 18 21 22 24 28
Solution
Prerequisite
The index of the sequences start with 0. Alternatively, they could start with 1, but then we would have to deduct 1, so to keep things simple, we start with 0.
Sequence A
$a = 10 * floor($n / 4);
The function floor() accepts a numeric value, and will cut off the fraction.
Also see https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.
Sequence B
$b = 2 ** ($n % 4);
The operator ** combines a base with the exponent and calculates the result of raising base to the power of exponent.
In PHP versions prior to PHP 5.6 you will have to resort to using pow(), see http://php.net/manual/en/function.pow.php.
The operator % combines two values and calculates the remainder of dividing the former by the latter.
Total
$value = $a + $b;
Putting it together
$input = 20;
// sequence a
$a = function ($n) {
return 10 * floor($n / 4);
};
// sequence b
$b = function ($n) {
return 2 ** ($n % 4);
};
// collect values in an array
$values = [];
// use a for loop, stop looping when value is greater than input
for ($n = 0; $input >= $value = $a($n) + $b($n) ; ++$n) {
$values[] = $value;
}
echo implode(' ', $values);
For reference, see:
http://php.net/manual/en/control-structures.for.php
http://php.net/manual/en/function.floor.php
http://php.net/manual/en/language.operators.arithmetic.php
http://php.net/manual/en/function.implode.php
For an example, see:
https://3v4l.org/pp9Ci

Fill an array with random numbers while obeying designated sum, count, and number boundaries

I have to fill an array with random numbers to satisfy a few conditions:
The number of elements in the result array must match the designated number.
The sum of the numbers in the result array must equal the designated number.
Random numbers must be selected between designated lower and upper bounds.
For example:
Sum of the array: 130
Total array elements: 3
Random integers' lower bound: 23
Random integers' upper bound: 70
Possible result:
array(23, 70, 37)
What to do now? How to split/divide my number?
I started with this (pseudo code):
i=0;
while(sum(number) > 0 and i < arraykeys){
x = randomize(from, to)
number = number - x
myarray[i] = x
i++
}
This should work for you:
Code explanation
Workability
The first thing we need to check is, if it is possible to build the goal out of numbers from the scope:
if(checkWorkability($result, $goal, $amountOfElementsLeft, $scope))
Means it just uses the highest values possible and looks if it is bigger than the goal.
While loop
In the while loop we need to check if we still have elements left which we can use:
while($amountOfElementsLeft > 0)
Scope adjustment
Every iteration we need to check if we need to adjust the scope, so that at the end we will be able to build the goal.
This means if the current sum of numbers + the highest possible number is bigger than the goal, we need to make the max value of the scope smaller.
Also on the opposite side we need to make the min value of the scope bigger, when we can't reach our goal anymore.
Code
<?php
$goal = 130;
$amountOfElementsLeft = 3;
$scope = [23, 70];
$result= [];
function adjustScope(array $result, $goal, $amountOfElementsLeft, $scope) {
$newScope = $scope;
if($amountOfElementsLeft == 1) {
$leftOver = $goal - array_sum($result);
return [$leftOver, $leftOver];
}
if((($goal - (array_sum($result) + $scope[1])) / ($amountOfElementsLeft - 1)) < $scope[0])
$newScope[1] = (int) ($goal - array_sum($result)) / ($scope[0] * ($amountOfElementsLeft - 1));
elseif(($adjustTop = $goal - array_sum($result)) < $scope[1])
$newScope[1] = $adjustTop;
if(($adjustBottom = $goal - (array_sum($result) + $scope[0] + (($amountOfElementsLeft - 1) * $scope[1]))) < $goal && $adjustBottom > 0)
$newScope[0] = $scope[0] + $adjustBottom;
return $newScope;
}
function checkWorkability(array $result, $goal, $amountOfElementsLeft, $scope) {
if(array_sum($result) + $amountOfElementsLeft * $scope[1] >= $goal)
return TRUE;
return FALSE;
}
if(checkWorkability($result, $goal, $amountOfElementsLeft, $scope)) {
while($amountOfElementsLeft > 0) {
$scope = adjustScope($result, $goal, $amountOfElementsLeft, $scope);
$result[] = rand($scope[0], $scope[1]);
$amountOfElementsLeft--;
}
}
print_r($result);
echo array_sum($result);
?>
possible outputs:
Array
(
[0] => 58
[1] => 30
[2] => 42
) -> 130
Array
(
[0] => 35
[1] => 54
[2] => 41
) -> 130
Array
(
[0] => 52
[1] => 51
[2] => 27
) -> 130
I've written a custom function for portability and to meaningfully implement some guard conditions which throw exceptions when incoming parameters make the desired result impossible.
Loop one less than $count times -- this is because the final element in the returned array is determined by the difference between the desired total and the sum of the randomly acquired values.
Adjust the lower and upper bounds of the $scope array (if required) to ensure a successfully populated return array.
Get a random integer, push it into the return array, then subtract it from the $total.
When the looped processes are finished, push the remaining $total value as the final element in the return array.
Code: (Demo)
function getRandWithStipulations(int $total, int $count, array $scope): array
{
if ($scope[0] > $scope[1]) {
throw new Exception('Argument 3 (\$scope) is expected to contain a minimum integer then a maximum integer.');
}
if ($scope[0] * $count > $total) {
throw new Exception('Arguments 2 (\$count) and 3 (\$scope) can only exceed argument 1 (\$total).');
}
if ($scope[1] * $count < $total) {
throw new Exception('Arguments 2 (\$count) and 3 (\$scope) cannot reach argument 1 (\$total).');
}
$result = [];
for ($x = 1; $x < $count; ++$x) { // count - 1 iterations
$scope[0] = max($scope[0], $total - ($scope[1] * ($count - $x)));
$scope[1] = min($scope[1], $total - ($scope[0] * ($count - $x)));
$rand = rand(...$scope);
$result[] = $rand;
$total -= $rand;
}
$result[] = $total;
return $result;
}
try {
var_export(
getRandWithStipulations(
130,
3,
[23, 70]
)
);
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage();
}
A few random results:
[60, 34, 36]
[23, 59, 48]
[67, 36, 27]
[47, 23, 60]

fill 2 dimensional array random in a bingo way

I've got these two functions:
function drawNumber($drawnNumbers){
$unique = true;
while ($unique == true){
$number = mt_rand(10, 69);
if (!in_array($number, $drawnNumbers)){
return $number;
$unique = false;
}
}
}
fillCard(); ?>
It's a bingo game. The card gets filled with random Numbers. But I can't get it like this:
column column column column column column
row 10 13 16 14 16 19
row 24 26 28 29 23 21
row 36 33 39 30 31 35
row 46 48 42 45 43 47
row 59 56 51 52 58 50
row 60 65 68 62 61 67
So I would like to have the first row with numbers from 10 to 19
the second row from 20 to 29 and so on.
I tried like this
<?php drawnNumber(): $number = mt_rand(0,9);
fillArray(): $number = $row . $number; ?>
But that doesn't work, because there are double numbers in the card.
So before that I tried it in a different way,with in_array:
<?php
function fillCard(){
$card = array();
/* fill card with random numbers */
for($i = 0, $min = 10, $max = 19; $i < 6; $i++, $min+=10, $max += 10)
{
for($j = 0; $j < 6; $j++)
{
$number = mt_rand($min,$max) ;
if(!in_array($number, $card){
$card['row' . $i]['column' . $j]['number'] = $number;
$card['row' . $i]['column' . $j]['found'] = 0;
}
}
}
var_dump($card);
return $card;
} ?>
But there are still double random numbers in the card.
I tried a few other thinks in the last two weeks, but I just can't get it to work together.
If one thing succeeds the other thing fails.
I can get the random numbers but not unique random numbers in the card.
I hope someone can help me.
(for extra information: it's a bingo game. So drawnNumber() are the "balls", which get drawn
and stored in the array $drawnNumbers, they also are unique random numbers. fillCard() is the
function that fills the bingo card and checks if $drawNumber is in $card)
I would appreciate some help, if someone can tell me how to get it to work. Maybe in
an algorithm way or else some code?
Thank you in advance.
In general, you draw from some kind of box, right? So do the same, have an array with all available numbers and once you get a random number out of it, remove it, so the next time you search for a number, you will only pick from the remaining ones. Small example:
a[0] = 1
a[1] = 2
a[2] = 3
a[3] = 4
we pick a random number between 0 and 3 inclusive (0 and the length - 1 of a that is). Let's say we picked index 2, then a will look like:
a[0] = 1
a[1] = 2
a[2] = 4
Now if you draw a number between 0 and 2 (note that you take the length - 1 of a!), you won't re-pick the already chosen number in any way thus giving you unique numbers ALL the time.
P.S. this is a simplified version, but now if you can apply that to yourself and, for your example, create several arrays you will pick from.
The simplest way would be to have an additional flat array to keep track, and loop mt_rand
Here's an example of the meat of things:
$drawn = array();
// Loop around until you have a new number in the desired range
do {
$number = mt_rand($min,$max);
} while(in_array($number, $drawn));
// And save it to the $drawn array
$drawn[] = $rand;
To clarify, the above snippet (without the initialization of $drawn) is meant to replace the line
$number = mt_rand($min,$max) ;
in your code.
define('NB_ROWS', 6);
define('NB_COLS', 6);
$rows = range(10, NB_ROWS * 10, 10);
$bingo = array();
foreach($rows as $rowIndex)
{
$availNumbers = range(0, 9);
$line = array();
for($cellIndex = 0; $cellIndex < NB_COLS; $cellIndex++)
{
// pick a random value among remaining ones for current line
$numIndex = rand(0, count($availNumbers)-1);
list($value) = array_splice($availNumbers, $numIndex, 1);
$line[] = $value + $rowIndex;
}
$bingo[] = $line;
}
print_r($bingo);

Calculate average percentage difference in a php array

Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 3
[6] => 1
)
I was wondering how one would go about working out the average percentage difference between the current value in an array and the next value. If the next value were a larger one, it would perform like so. (ie keys [0]-[1] 1/2 * 100 = 50). If it were a smaller value it would perform like so. (ie keys [4]-[5] = 3/5 * 100 = -60).
The following will represent what I am aiming to do with these percentage calculations.
1/2 * 100
2/3 * 100
3/4 * 100
4/5 * 100
3/5 * 100 (negative)
1/3 * 100 (negative)
Total : total/count
This will iterate through the list and then work out the average from the count. I have looked into splitting arrays but don't see how else I could do this.
$count = count($num);
foreach ($num as $value) {
array_chunk($num, 1);
if($value<$value){
$total1 = $total1 + ($value/$value)*100;
}
if($value>$value){
$total2 = $total2 + ($value/$value)*100;
}
}
$average = (($total1-$total2)/$count);
print($average);
I understand the above code is incorrect, but I hope it reveals where I am getting at with this.
Any help would be greatly appreciated.
You don't want to use foreach as you'll always be needing two array elements. Note that this snippet does not protect you from 0 values. These will make your script fail.
$num = array(1, 2, 3, 4, 5, 3, 1);
$total = 0;
// The number of percent changes is one less than
// the size of your array.
$count = count($num) - 1;
// Array indexes start at 0
for ($i = 0; $i < $count; $i++) {
// The current number is $num[$i], and the
// next is $num[$i + 1]; knowing that it's
// pretty easy to compare them.
if ($num[$i] < $num[$i + 1]) {
$total += (100 * $num[$i] / $num[$i + 1]);
}
else {
$total += (-100 * $num[$i + 1] / $num[$i]);
};
};
echo ($total / $count);

Categories