I'm trying to figure out an algorithm to come up with an arrayed result that are equidistant alternating points from the center (can be percent based). So, my end result would be something like:
X = 20 (separation distance based on # of items) - 100 / 5 (5 items spread out over 100%)
A = 50 (center point)
B = 70 (A + 20)
C = 30 (A - 20)
D = 90 (B + 20)
E = 10 (C - 20)
Another result would be if we have 10 items (X = 100 / 10):
A = 50 (center point)
B = 60 (A + 10)
C = 40 (A - 10)
D = 70 (B + 10)
E = 30 (C - 10)
F = 80 (D + 10)
G = 20 (E - 10)
H = 90 (F + 10)
I = 10 (G - 10)
J = 100 (H + 10)
If it's important, I'm trying to arrive at this algorithm using PHP. I'm not much of a Math wiz so I'm not sure if there's a name for this type of calculation. Thanks!
You could write a function like:
function getArrayEquidistant($startValue, $step, $nbEntries)
{
$i = 0;
$count = 1;
$final = array();
$final[] = $startValue;
while($i < $nbEntries)
{
if ($i % 2 == 0)
$final[] = $startValue + ($count * $step);
else
{
$final[] = $startValue + ($count * $step);
$count++;
}
$i++;
}
retun $final;
}
Where $startValue is the initial value (at index 0), $step is the value added or sub at each iteration, and $nbEntries the number of entries after the initial value.
As example:
print_r(getArrayEquidistant(50, 20, 10));
will give you:
Array
(
[0] => 50
[1] => 70
[2] => 30
[3] => 90
[4] => 10
[5] => 110
[6] => -10
[7] => 130
[8] => -30
[9] => 150
[10] => -50
)
If I understood you correctly, this should work:
function pointsArray($center, $numPoints) {
$arr = array();
$arr[0] = $center;
for($i = 1;$i < $numPoints; $i++)
$arr[$i] = $i%2 == 0 ? $center - ($i-1)*20 : $center + $i*20;
return $arr;
}
Than, you can use the function like this:
$PointsArray = pointsArray(50, 5); // {50,70,30,90,10}
Related
I am reading values over a (modbusTCP) connection. I get back an array with the following data:
print_r($recData) ;
Output: Array ( [0] => 67 [1] => 100 [2] => 33 [3] => 72 )
how do I get the values back as float? as result I should get the following:
229.718
my code dosent work... the data in $recData shout be a Float Big Endian Value
$i = ($recData[0]<<24) + ($recData[1]<<16) + ($recData[2]<<8) + ($recData[3]);
You may convert it inside PHP like that.
$number = [67, 100, 33, 72];
$strHex = implode('', array_map('dechex', $number));
$v = hexdec($strHex);
$x = ($v & ((1 << 23) - 1)) + (1 << 23) * ($v >> 31 | 1);
$exp = ($v >> 23 & 0xFF) - 127;
$float = $x * pow(2, $exp - 23);
echo round($float, 3);
gives
228.13
I have an array with rainfall amount for each month. I am doing some calculation in a foreach loop which starts from 0 index in the array. How can I start from the current month (say 4th month) and end at third month next year? Below is the code I have in hand.
public static function getWaterLevels($params)
{
$rainfall = $params["rainfall"];
$currentTime = Carbon::now();
$currentMonth = $currentTime->month;
$volume = 0;
$demand = $params["household_number"] * 140 * 30;
$tankSize = $params["tank_capacity"];
$waterLevels = array();
foreach ($rainfall as $amount){
$runoffAmount = 0.80 * ($amount - 2) * $params["roof_area"];
$volume = $volume + ($runoffAmount - $demand);
if ($volume > $tankSize)
{
$overflow = $volume - $tankSize;
$deficit = 0;
$volume = $volume - $overflow;
}
elseif ($volume < 0)
{
$deficit = abs($volume);
$overflow = 0;
$volume = 0;
}
else
{
$overflow = 0;
$deficit = 0;
}
array_push($waterLevels, array(
"volume" => $volume,
"overflow" => $overflow,
"deficit" => $deficit
));
}
return $waterLevels;
}
In the above function, I want to start the loop at $currentMonth - 1. The structure of rainfall array is like this:
array:12 [
0 => 59
1 => 57
2 => 54
3 => 76
4 => 76
5 => 87
6 => 82
7 => 83
8 => 88
9 => 91
10 => 84
11 => 74
]
I get some numbers from database. I would like round up these numbers this way:
Database => Round up number
34 => 0
89 => 100
421 => 400
561 => 600
4421 => 4000
6701 => 7000
45000 => 50000
91000 => 90000
132000 => 130000
Is there any php function to do this? So numbers under 1000 would be round up closest full 100. Over thousands would be rounded up to nearest full 1000 figure. And if number is over 10 000 then it would be always rounded up to closest full 10 000.
Hopefully you understand what I'm after.
Since I'm fed up of people not reading the damn question...
function myRound(int $number) : int {
// remove typehints if you're on old versions of PHP...
$magnitude = abs($number);
if( $magnitude < 1000) $precision = -2;
elseif( $magnitude < 10000) $precision = -3;
else $precision = -4;
return round($number,$precision);
}
IDEOne test
You can use some simple math(mostly to calc num length) and build in with negative precision round() function
function customRound($number) {
return round($number, -floor(log10($number)));
}
echo customRound(6701); // sample of usage
-floor(log10($number)) this part is to calc length of num - 1 and also it is negated for round() needs
Have a look at the round() function here
http://php.net/manual/en/function.round.php
and the ceil() function here
http://php.net/manual/en/function.ceil.php
Something like
$number = 1;
$number = ceil($number / 10) * 10;
echo $number;
Here is one solution:
$numbers = [
34,
89,
421,
561,
4421,
6701,
45000,
91000,
132000
];
foreach ($numbers as $number) {
$len = strlen((string)$number);
$precision = $len - 1;
$precision = $len <= 2 ? 2 : $precision;
$precision = $len > 4 ? 4 : $precision;
echo $number . ' => '. round($number, -1 * $precision) . PHP_EOL;
}
Outputs:
34 => 0
89 => 100
421 => 400
561 => 600
4421 => 4000
6701 => 7000
45000 => 50000
91000 => 90000
132000 => 130000
You can use a function like this:
$number = 45000;
function rounder($num)
{
$length = strlen($num);
if(is_int($num))
{
if($num < 100)
return round($num, -($length));
elseif($num < 1000 || $num <= 9999)
return round($num, -($length-1));
else
return round($num, -4);
}
}
echo rounder($number);
Though not tested, should work..
Hello I need to get N numbers from range between 2 big numbers, without the start and end numbers.
The (N) numbers must be on equal intervals... I will try to explain with small numbers:
<?php
$rangeStart = 0;
$rangeEnd = 100;
$n = 9;
In this example i need to get 10,20,30,40,50,60,70,80,90
I have try with 'for loop' but it is veeery slow, because I'm using range like 1207083600 ~ 1275512399
Will appreciate any help.
=====
This is what I call slow http://jsfiddle.net/pbF7N/1/
The start and end are timestamps and I need to extract 10 dates...
range() with its optional 3rd parameter to specify the step size...
range(10, 90, 10);
$range = range(10, 90, 10);
print_r($range);
Array
(
[0] => 10
[1] => 20
[2] => 30
[3] => 40
[4] => 50
[5] => 60
[6] => 70
[7] => 80
[8] => 90
)
Something like this maybe:
function nrange($num, $start, $end)
{
$out = array(); $i = 0;
$interval = floor(($end - $start) / ($num + 1));
while ($i++ < $num )
$out[] = $start + $i * $interval;
return $out;
}
Consider first your example case. Your numbers broke up the range [0..100) into 10 equal intervals, [0..10), [10, 20), etc. up to [90..100).
Notice that the number of intervals is $n+1. So you see that each interval is of length ($rangeEnd - $rangeStart) / $n.
Using this information, you can use range to step across $interval numbers at a time, i.e.,
$interval = ($rangeEnd - $rangeStart) / $n;
$range = range($rangeStart, $rangeEnd, $interval);
Lets say I have a range between 0 and 100 and I want an array returned containing 3 integers which are evenly distributed within that range, what would be the best way to do this?
For example:
Range: 0-100
Wanted: 3
Returned: 25, 50, 75
Pseudo code:
function distributeIntegers(int wanted, int rangeLow, int rangeHigh)
int increment = (rangeHigh - rangeLow) / (wanted + 1)
array r = new array()
for (int i = rangeLow + increment; i < rangeHigh; i += increment)
r.push(i)
return r
PHP:
function distributeIntegers($wanted = 3, $rangeLow = 0, $rangeHigh = 100){
$increment = ($rangeHigh - $rangeLow) / ($wanted + 1);
$r = array();
for ($i = $rangeLow + $increment; $i < $rangeHigh; $i += $increment)
$r []= $i;
return $r;
}
/*
examples:
call:
distributeIntegers();
returns:
[0] => 25
[1] => 50
[2] => 75
call:
distributeIntegers(4);
returns:
[0] => 20
[1] => 40
[2] => 60
[3] => 80
call:
distributeIntegers(5, 50, 200);
returns:
[0] => 75
[1] => 100
[2] => 125
[3] => 150
[4] => 175
*/
you can make use of array_chunk(), eg only
$end=100;
$a = range(0,$end);
$chunk=3;
foreach (array_chunk($a,$end/($chunk+1)) as $s){
print $s[0]."\n";
}
output
$ php test.php
0
25
50
75
100
you can get rid of the start (0) and end(100) points if not needed.
Here's a solution in groovy that gives the answers you want, you should be able to switch it to whatever language you're using:
def distributedValues(min, max, wanted) {
def incrementBy = (max - min)/(wanted + 1)
(1..wanted).collect { count -> min + (count * incrementBy) }
}
assert distributedValues(0, 100, 1) == [50]
assert distributedValues(0, 100, 3) == [25, 50, 75]
assert distributedValues(0, 100, 4) == [20, 40, 60, 80]
assert distributedValues(0, 100, 5) == [16.6666666667, 33.3333333334, 50.0000000001, 66.6666666668, 83.3333333335]
assert distributedValues(100, 200, 3) == [125, 150, 175]
You can use the rand function to get the random value between the specific ranges.
Use this code . This following function would return set of element in a array
function array_elements( $start = 0 , $end = 100 , $element =5 )
{
$myarray = array () ;
for ( $i = 0 ; $i < $element;$i++ )
{
$myarray[$i]= rand ( $start, $end );
}
return $myarray ;
}
print_r ( array_elements() ) ;