Approximate count in PHP - php

I have a website that contains a list of articles. I want to include a line that says how many articles there are in the DB, however I don't want it to show the exact count.
I would like it to round down to the nearest 10, so for example for 105 articles I would like it to say "100+", etc.
How would I go about doing this?

Quite simple:
floor($num / 10) * 10
docs

To do something similar you have to use the logarithm with base = 10 and round it
$exp= floor(log($num)/log(10));
$num = pow(10,$exp)."+";
This works with 10, 100, 1000 ecc, i think it better do what you asked.

$count = 105;
$nearest10 = floor($count / 10) * 10;

printf("%d0+", $count * 0.1);
or
echo substr($count, 0, -1), '0+';
And the roundDocs function does support it out of the box, too:
round($count, -1, PHP_ROUND_HALF_DOWN);
but the plus-sign is missing.

First of all, you will need to use the COUNT() Aggregate function of MySQL to fetch the total number of results, or something like that.
Then you will need to use the modulo operator (%) with 10 as the base, and then deduct that value from the main result, which will be something like this:-
$sql = "SELECT COUNT(id) AS `total_num_records` FROM `table`";
$resource = mysql_query($sql);
$result = mysql_fetch_array($resource);
$totalRecords = $result['total_num_records'];
if ($totalRecords > 0) {
$remainder = $totalRecords % 10;
$showHumanFriendlyRecords = ($totalRecords - $remainder);
$strHumanFriendlyRecords = $showHumanFriendlyRecords . "+";
}
Hope it helps.

Related

How can I create an array of a divided number in PHP?

I want to create an array in PHP by dividing a number. So for example when I have the number 200 and I divide it through 0,10, I need to get an array with 2k entries of 0,10.
But when I have a division like 233,12 / 0,10, I also need the array but the last possible entry needs to be a bit higher so that it fills the sum up.
Actually I have no code. This is too complex for me. Maybe someone has an idea. I've did everything around this but got really stuck here...
$number = 200;
$divider = 0.10;
So you want to have an array with 2k entries each having the value 0.1 in them?
So something like
$number = 200;
$divider = 0.1;
$totalArraySize = $number / $divider;
$result = [];
$result = array_fill(0, $totalArraySize, $divider);
However to make it slightly bigger in case of (for example) 233,12/0,1 you would simply need to ceil() the $totalArraySize to round it up to the nearest full integer. And to make sure that the last entry has the difference you basicly need to calculate it. You get it by taking what you expect to be the sum and subtract the values you know to be right. So (totalSize - 1) * 0,1 .. would give you in this example 233,1 so the last entry would be then 233,12 - 233,1 = 0,02
$number = 233,12;
$divider = 0.1;
$totalArraySize = ceil($number / $divider);
$wasRoundUp = $number % 1 === 0
$result = [];
$result = array_fill(0, $totalArraySize, $divider);
if ($wasRoundUp)
$result[$totalArraySize] = $number - (($totalArraySize - 1) * 0,1)
Edit: Actually I realised that my logic to see if it was round up was wrong. I cannot rely on modulo 1 division here as 233,1 would be divisible by 0.1 in an even amount. So we need to check if totalArraySize != ($number / divider).
So new code would be
$number = 233,12;
$divider = 0.1;
$totalArraySize = ceil($number / $divider);
$wasRoundUp = $totalArraySize != ($number / $divider);
$result = [];
$result = array_fill(0, $totalArraySize, $divider);
if ($wasRoundUp)
$result[$totalArraySize] = $number - (($totalArraySize - 1) * 0,1)
Edit 2:
To reflect the question in the comment and "fix" an issue with the code here's the new answer. To fill up the last entry it now takes the divider value and not hardcoded 0.1 which would have to be changed correctly. And due to floating point calculations you would need to round the last value to two decimal points. I cannot guarantee if thats the best aproach tho to avoid the floating point rounding issue you might get there
$number = 164.85;
$divider = 0.2;
$totalArraySize = ceil($number / $divider);
$wasRoundUp = $totalArraySize != ($number / $divider);
$result = array_fill(0, $totalArraySize, $divider);
if ($wasRoundUp)
$result[$totalArraySize] = round($number - (($totalArraySize - 1) * $divider), 2);

How to limit MySQL query result to specific results?

I have a news table in MySQL Database I query the table and show the title of the news in one PHP pages but now the table getting bigger so I want to divide the results into pages I mean to show each 50 news title in one page (pagenation).
I use this query to bring the news :
SELECT news.*, categories.category, users.username
FROM news INNER JOIN
users on news.user_id = users.id INNER JOIN
categories on categories.id = news.category_id
order by news.timestamp DESC
limit $min,$max
and this is part of the PHP page (How I calculate the max and min)
$news_per_page = 50;
if(!empty($_GET['p_n']))
{
$p_n = $_GET['p_n'];
$max = $news_per_page*$p_n;
$min = ($max - $news_per_page);
}
else
{
$p_n = 1;
$max = 50;
$min = 0;
}
$news = all_news($max,$min);
The sql giving me wrong result when i pass the limits I do not know why. Is it wrong to specify the max and min of sql query by this way?? Should I correct something in this code?
The LIMIT clause, as explained in the docs, takes arguments offset and count. So if you want to get, for example, results from 201 to 250, you would use LIMIT 200, 50. Start by renaming your variables $min and $max to $offset and $count, and from there everything will fall into place.
Pseudocode:
offset = (requestedPageNumber - 1) * rowsPerPage;
count = rowsPerPage;
PHP Code:
(assuming page number is 0-based)
$rowsPerPage = 50;
$page = empty($_GET['p_n']) ? 0 : $_GET['p_n'];
$offset = $rowsPerPage * (int) $page;
$news = all_news($offset, $rowsPerPage);
If you've got problems handling pagination properly, I suggest you use some code that is working, for example a pagination class that takes three parameters:
The current page.
The total count.
The number of items per page.
And then that class will generate the LIMIT clause for you. Example:
$pageNumber = 1;
$totalCount = 17;
$perPage = 5;
$pagination = new LimitPagination($pageNumber, $totalCount, $perPage);
echo $pagination, "\n";
This would output
LIMIT 0, 5
because you'er on the first page. Such a class then could also filter out those problems you have here, for example setting to a negative page - just automatically. And also it can provide a lot of extra data, like the next and previous page, the current page, the number of total pages, if it is the first or the last page and what not:
$pagination->setPage(-2);
echo $pagination, "\n";
echo "Current: ", $pagination->getPage(),
"; Total: ", $pagination->getTotalPages(),
"; Previous: ", $pagination->getPreviousPage(),
"; Next: ", $pagination->getNextPage(),
"\n";
Output:
LIMIT 0, 5
Current: 1; Total: 4; Previous: 1; Next: 2
This is then easy to integrate with different code, including yours:
$pagination = new LimitPagination($_GET['p_n'], $totalCount, 50);
$limit = sprintf("%d, %d", $pagination->getOffset(), $pagination->getCount());
This should easily do it. Class is here as Gist: https://gist.github.com/4469154
You need to set start (this you can achieve by using current page and per page property) and the second information is how many results you want (again per page property).
LIMIT . ($p_n - 1) * $news_per_page .', ' . $news_per_page
So, in your script it will be:
if(!empty($_GET['p_n']))
{
// You need to protect your variables for SQL injection. For numbers (int) or integer() function it is enough.
$p_n = (int) $_GET['p_n'];
$max = (int) $news_per_page;
$min = (int) ($p_n - 1) * $news_per_page;
}
else
{
$p_n = 1;
$max = 50;
$min = 0;
}
The correct code is:
$news_per_page = 50;
if(!empty($_GET['p_n']))
{
$p_n = intval($_GET['p_n']);
$min = ($p_n-1) * $news_per_page;
$max = $news_per_page;
}
else
{
$p_n = 1;
$max = 50;
$min = 0;
}
$news = all_news($max,$min);
While $_GET['p_n'] is page_number you dont' need to make any multiplies

Auto increase value php in file based on number entered

I have 5 different variables that I need to calculate. Right now these work, but what I want to do is have the price recalculate every 50 increase. Now, I can code into the form to only allow a maximum purchase of 50 at a time, but I want to allow for as many of each as the person has money for (that is what the numbers are). So I think what I need is a parabola style formula that auto increases every 50, but I don't know exactly what I'm looking for or how to implement it.
$resprice = 20000+($cityFetch['residential']*502)+($cityNum*1000);
$comprice = 18000+($cityFetch['commercial']*506)+($cityNum*1000);
$indprice = 23000+($cityFetch['industrial']*508)+($cityNum*1000);
$landprice = 600+($cityFetch['land']*.008);
$milprice = 25000+($cityFetch['military']*512)+($cityNum*1000);
EDIT: I was indicated that a loop will work for this.
EDIT3: Finally landed on this, Havvy helped me out on IRC
$cityCheck = mysql_query("SELECT * FROM cities WHERE nation='$nation'");
$cityNum = mysql_num_rows($cityCheck);
function determinePrice($baseCost, $scalar, $current, $bought) {
$min = $baseCost + $scalar * ($current + 1) + ($cityNum * 1000);
$max = $baseCost + $scalar * ($current + $bought) + ($cityNum * 1000);
$average = ($min + $max) / 2;
return $average * $bought;
}
$resprice = determinePrice(20000, 502, $cityFetch['residential'], $cityFetch['residential']);
$comprice = determinePrice(18000, 506, $cityFetch['commercial'], $cityFetch['commercial']);
$indprice = determinePrice(23000, 508, $cityFetch['industrial'], $cityFetch['industrial']);
$milprice = determinePrice(25000, 502, $cityFetch['residential'], $cityFetch['military']);
$landprice = 600+($cityFetch['land']*.008);
I use a step size of 1, instead of 50. It's more logical (one less magic number) to not give discounts based on how much you buy at a time, and it would be confusing to new players having a stepwise-linear function.
The reasoning behind this function can be found at http://betterexplained.com/articles/techniques-for-adding-the-numbers-1-to-100/.
function determinePrice($baseCost, $scalar, $current, $bought) {
$min = $scalar * ($current + 1) + ($cityNum * 1000);
$max = $scalar * ($current + $bought) + ($cityNum * 1000);
$average = ($min + $max) / 2;
return $average * $bought;
}
Using it would look something like this:
$resprice = determinePrice(20000, 502, $cityFetch['residential'], $resBought);
It won't work for land though, because land doesn't include the city price in it. For land, you can copy the function and remove the $cityNum * 1000 portions. You could also add in a $isLand parameter to the signature, and use a ternary operator to add 0 instead.
If you don't like that $cityNum has to already be declared with the proper value before declaring this function, you can always add it to the function signature, making it a pure function.
$count=1
if($count==50)
{
You increase the prices then
$count=1;
}
$resprice = 20000+($cityFetch['residential']*502)+($cityNum*1000);
$comprice = 18000+($cityFetch['commercial']*506)+($cityNum*1000);
$indprice = 23000+($cityFetch['industrial']*508)+($cityNum*1000);
$landprice = 600+($cityFetch['land']*.008);
$milprice = 25000+($cityFetch['military']*512)+($cityNum*1000);
$count++;

PHP: Get thousand from number

When the user enters a number from 1000 and above I want to be able to get the thousand for that number in an array.
For example…
Number entered by user: 165124
My array should return:
array('thousand_low' => 165000, 'thousand_high' = 165999)
Thanks!
The complete array-returning function, using PHP's native floor and ceil functions:
function get_thousands($num) {
return array(
'thousand_low'=>floor($num/1000)*1000,
'thousand_high'=>ceil($num/1000)*1000-1
);
}
Untested (edit: but should work ;) ):
$number = 165124;
$low = floor($number / 1000) * 1000;
$high = $low + 999;
Something like this:
$num = 165124;
$result = array();
$result['thousand_low'] = floor($num / 1000) * 1000;
$result['thousand_high'] = $result['thousand_low'] + 999;
Have a look at the round function (http://php.net/manual/en/function.round.php) - you can specify the precision so you can customise the magnitude of the rounding.
array('thousand_low' => floor($int/1000)*1000,
'thousand_high' => floor($int/1000)*1000+999);
Haven't used php in quite a while but i think it should look something like this :
$num_input = 165124;
$array['thousand_low'] = floor($num_input / 1000) * 1000;
$array['thousand_high'] = $array['thousand_low'] + 999;

Calculating number of results in a specific page using pagination

I have a search result from MySQL query or Array or something else. The result gave a variable $totalfiles say for example 25. The number of results is limited to $limit, here 12. The maximum number of pages calculated, $maxpages, will be 3.
As we consider the case, we will get 12 results for pages 1 and 2, and 1 for page 3.
What is the easiest way to predict (or calculate) the number of results in a specific page using variables $totalfiles, $limit, $maxpages and $pagenumber using PHP? I don't think all these 4 variables are necessary for doing this.
The only page that is allowed to have a number that is different from $limit is the last one. Don't forget that. And the last page will always have the remainder of the integer division
$last_page_items = $totafiles % $limit;
If $last_page_items is 0, means that you have all pages with $limit items
also,
$pages = ceil($totalfiles / $limit);
R = Number of rows on a given page, P, where P starts at 1.
T = Total rows
L = Rows per page
R = T - ((P-1) * L)
Then just add a check afterwards to set R to 0 if R < 0.
Code:
function get_num_rows_on_page($page, $total_rows, $per_page) {
$on_page = $total_rows - ( ($page-1) * $per_page );
return $on_page < 0 ? 0 : $on_page;
}
Max pages: Total files, divided by the limit. If the remainder is greater than 0, add one.
$maxpages = $totalfiles/$limit;
if ($totalfiles % $limit > 0) $maxpages++;
Number on current page: if Page number less than Max page, there are limit results. If Page number is the Max page, there are (Remainder of Total Files divided by limit) results if that remainder is greater than 0, otherwise limit.
$results = $limit;
$rem = $totalfiles % limit;
if ($pagenumber == $maxpages && $rem > 0) $results = $rem;
If you want to distribute the results evenly in the maximum number of pages, which is 3 as you have suggested, you can use:
$results_per_page = ($totalfiles/$maxpages);
Otherwise, you already have the number of results per page calculated on your $limit variable.
Try this:
function getPageSize($total, $maxpages, $pagenumber){
$itemsperpage=intval($total/$maxpages);
if($pagenumber == $maxpages){
$itemslastpage=abs($total-($itemsperpage*$maxpages));
return $itemslastpage;
}else{
return $itemsperpage;
}
}
// should print '5'
echo getPageSize(29,6,6) . "\n";
// should print '7'
echo getPageSize(14,2,1) . "\n";
Note that $limit is not needed as it is only used to control results from database.

Categories