PHP combine array_sum and multiplication in foreach - php

how can I multiply the result of an array_sum in a foreach loop?
Example: I have product1 with a value of 10, product 2 with a value of 20. Each product is bought twice: I need to have (10 + 20)*2 = 60. I tried the following:
($number[$key]) * (array_sum($totprod[$key]))
but this is not working (result = blank).
Thank you for your help
Here is my foreach ($number = quantity)
foreach ($number as $key => $value){
$total[$key] = array($product1[$key], $product2[$key]);
echo "<pre>Quantity " . $number[$key] . "Price product1 " . $product1[$key] . " Price product2 " . $product2[$key] . " = Total price " . $number[$key] * array_sum($total[$key]) . "</pre>";
}

I don't think that sum is the best approach here since
(10 + 20) * 2 = 2*10 + 2*20
You probably better just calculate totals for each products and sum all results as it would work in the general case (1 productX + 6productY).
Now generally speaking, dealing with money, you should avoid array_sum and all php native math operators as you could have some surprises like total VAT != sum of all product's VAT.
When dealing with money, or when precision must be controlled, use bcmath http://php.net/manual/en/book.bc.php

Related

Best way to round down in PHP

I have a form, when a user fills in the total number of bottles they have, it inserts into a database and then should sum up how many cases there are.
For example in wine - there are 12 bottle cases, if a user puts in 100 bottles, it should divide this by 12 and give the sum of 8.33333333.
$bottles = "100";
What is the best way to round this down to just the number 8 and then work out how many bottles are left that never made it into a full case?
Hope this makes sense.
You can use floor
$bottles = "100";
$case = floor( $bottles / 12 );
echo $case;
Will result to 8
Documentation: http://php.net/manual/en/function.floor.php
If you want to check the bottles left, you can use modulo
$bottles = "100";
$left = $bottles % 12;
Will result to 4
You can use floor to round down, and the modulo (%) operator to determine how many bottles are left.
$bottles = 100;
$bottles_per_case = 12;
print "There are " . floor($bottles / $bottles_per_case) . " cases...";
print "With " . ($bottles % $bottles_per_case) . " bottles left over";
$bottles = "100";
$case = (int) $bottles / 12 ;
echo $case;
$left = $bottles % 12;
echo '<br>left: ' . $left;

Inventory product computation and conversion

I am coding inventory of products. Now I am in the process of computing or converting the items into a larger unit.
For example:
Product A: 1 box = 12 bottles
The user can input a data like 3 boxes and 13 bottles when adding a transaction. And the new value for Product A will be 3 boxes and 13 bottles in storage. Data will save into database tbl_transaction.
How can I automatically turn/convert the items as a whole like 4 boxes and 1 bottle in storage to add in my tbl_storage?
I have tried this formula but I am afraid it is not accurate when the number of bottles is in the decimal point.
$bottles = 13;
$box = 12;
$remaining_in_bottle = number_format($bottles / $box);// this will only convert the bottle into box (also tried float but not sure what I am doing)
$total_box = 3 + ???;
echo $total_box." boxes and ".$remaining_in_bottle ." bottles in storage
I am assuming the user is inputing just digits as values for boxes and bottles, but if not you will simply need to extract these values from the string before performing the following calculations:
Code: (Demo)
$bottles_per_box=12;
$user_input_bottles=13;
$user_input_boxes=3;
if($user_input_bottles>$bottles_per_box){
// add truncated integer to box count. DO NOT USE ROUND(), USE FLOOR()
$user_input_boxes+=floor($user_input_bottles/$bottles_per_box);
// store remainder after division
$user_input_bottles=$user_input_bottles%$bottles_per_box;
// ^-- modulo operator
}
echo "New Bottles Total: $user_input_bottles\n";
echo "New Boxes Total: $user_input_boxes\n";
Output:
New Bottles Total: 1
New Boxes Total: 4
I assume that you want to input different for tbl_transaction and tbl_storage.
CODE
//Max bottle per box
$box_max_bottles = 12;
//User Input
$input_box = 3;
$input_bottle = 13;
//Transaction
$transaction = (($input_box > 1) ? $input_box . ' boxes' : $input_box . ' box')
. ' and ' . (($input_bottle > 1) ? $input_bottle. ' bottles' : $input_bottle. ' bottle'). ' in storage';
//Data will save into database tbl_transaction
echo $transaction;
//Get the remainder which is the remaining bottle
$total_bottle = $input_bottle % 12;
//Get the total boxes and divide the bottle into 12
$total_box = floor($input_box + ($input_bottle / 12));
echo "<br />";
//Storage
$storage = (($total_box > 1) ? $total_box . ' boxes' : $total_box . ' box')
. ' and ' . (($total_bottle > 1) ? $total_bottle . ' bottles' : $total_bottle . ' bottle'). ' in storage';
//Data will save into database tbl_storage
echo $storage;
OUTPUT
Transaction
3 boxes and 13 bottles in storage
Storage
4 boxes and 1 bottle in storage

Looking for a more elegant solution to this loop

I tried asking this earlier, but I don't think I phrased the question correctly so I worked out something that got me the result I was after and now am hoping that it will help someone help me.
Problem: I have 10 items. If you buy 1, it's $10. I will sell you the second one for $9. I will sell you the third item for $8. I will keep taking off money until we get to $5/item because that is the lowest I will sell it for. So, if you buy all 10, it will cost you $65.
This is the pricing model I am trying to achieve, except at a much larger scale. Instead of a handful of items using dollars, I'm talking about up to millions and using fractions of pennies.
This is my current code:
<?php
function getCost($num_items)
{
$min_price = 0.002;
$max_price = 0.007;
$discount_range = 1000000;
$discount_per_additional_item = ($max_price - $min_price) / ($discount_range - 1);
$price_per_unit = MAX($min_price, ($max_price - ($num_items - 1) * $discount_per_additional_item) );
return $price_per_unit;
}
$array = [100, 1000, 10000, 100000, 200000, 300000, 400000, 500000, 600000, 700000, 800000, 900000, 1000000];
foreach ($array as $value)
{
$sum = 0;
for ($i = 0; $i < $value; ++$i)
$sum += getCost($i);
echo number_format($value) . ' | $' . number_format($sum) . "\n";
}
Which results in:
100 | $1
1,000 | $7
10,000 | $70
100,000 | $675
200,000 | $1,300
300,000 | $1,875
400,000 | $2,400
500,000 | $2,875
600,000 | $3,300
700,000 | $3,675
800,000 | $4,000
900,000 | $4,275
1,000,000 | $4,500
I'm using $array as a sanity check where in the real world, I would simply calculate for the actual number the customer is being charged for.
My question is: Is there a way to accomplish this without using a for loop? Something, perhaps, more elegant?
I made an example online: http://sandbox.onlinephpfunctions.com/code/47e270dbad8cbe16c9ea906ffd2dce098a52fbca
This code will have the same output, and does not have the inner loop:
$min_price = 0.002;
$max_price = 0.007;
$discount_range = 1000000;
$discount_per_additional_item = ($max_price - $min_price)/($discount_range - 1);
$num_progressively_discounted_items =
ceil(($max_price - $min_price) / $discount_per_additional_item);
foreach ($array as $value) {
$num_items_above_min = min($value, $num_progressively_discounted_items);
$num_items_at_min = $value - $num_items_above_min;
$sum = $num_items_at_min * $min_price +
$num_items_above_min * $max_price -
$discount_per_additional_item
* $num_items_above_min * ($num_items_above_min - 1)/2;
echo number_format($value) . ' | $' . number_format($sum) . "\n";
}
This is what it does:
It first checks how many times the unit discount can be subtracted from the original price before hitting the minimum price. If more than the number of items you are buying, then this calculated figure is corrected to that number of items.
The remaining number of items (if any) are also taken note of: these will all have the minimum price.
The sum consists of two parts. The easy part is represented by the number of items that will go for the minimum price, and it is a simple multiplication.
The second part of the sum consists of an always decreasing term, or otherwise put: it is the maximum price for the number of items that don't go for the minimum price, minus the sum of 0+1+2+3+4+5...+n. For that the formula is known: n(n-1)/2.
Like I mentioned in comments, there is something strange in your code: for $i=0 the value returned by getCost($i) is higher than the max price, as the unit discount gets added to it. This can be corrected by starting your inner loop with $i=1. Anyway, this means there is a tiny difference in the result of my proposed code, as it does not have this peculiarity. But as the discount per unit is so tiny, you don't actually notice it in the printed output.
You can do this a little bit more functional style:
function sumOfNaturalSeries($n)
{
return ((1 + $n) / 2) * $n;
}
$minPrice = 0.002;
$maxPrice = 0.007;
$discountRange = 1000000;
$discountStep = ($maxPrice - $minPrice) / $discountRange;
$getPrice = function ($numberOfItems) use (
$minPrice,
$maxPrice,
$discountRange,
$discountStep
) {
if ($numberOfItems <= $discountRange) {
return $maxPrice * $numberOfItems - sumOfNaturalSeries($numberOfItems - 1) * $discountStep;
}
$itemsAboveRange = $numberOfItems - $discountRange;
return $maxPrice * $discountRange - sumOfNaturalSeries($discountRange - 1) * $discountStep + $minPrice * $itemsAboveRange;
};
$array = [100, 1000, 10000, 100000, 200000, 300000, 400000, 500000, 600000, 700000, 800000, 900000, 1000000];
$sums = array_map($getPrice, $array);
var_dump($sums);
var_dump(array_map('number_format', $sums));
Here is demo.
Take a notice on computational error.

how to translate array information into statement in php?

I am working on website that suppose to compare products. So I have reached to this following array
Array ( [iPhone 4 8GB Black] => 319 [iPhone 4S] => 449 [iphone 5] => 529 )
the key of the array is product name and the value of the array is the price. now i want to translate this array into statements like
iphone 4 8GB Black is cheapest!
iPhone 48GB Black is £130(calculation:449-319) cheaper than iphone 4S.
iPhone 48GB Black is £210(calculation:529-319) cheaper than iphone 5.
iPhone 4S is £80(calculation:529-449) cheaper than iphone 5.
iphone 5 is most expensive product from your chosen list.
Please help me on how to output those statements from an array. Your suggestion to do something else with this array in-terms of comparing would also be great. Thank you.
First, you have to sort your array with asort (in order to keep the association between your index and your values, and sort on values).
asort($yourArray);
Then, as your array is sorted, you can isolate price and names.
$names = array_keys($yourArray);
$prices = array_values($yourArray);
At this point you have 2 numerical indexed array containing your label and your prices and these 2 arrays are synchronized.
Finally, you just have to loop from 0 to the length of your array (one of them, its the same size) and made your process:
for($i = 0 ; $i < count($names) ; $i++)
{
if ($i == 0)
{
// First product -> cheapest
echo "The product " . $names[$i] . " is cheapest";
}
else if ($i == (count($names) - 1))
{
// Last product, the most expensive
echo "The product " . $names[$i] . " is the most expensive product of the list";
}
else
{
// calculate the diff between current product and first product
$diff = $price[$i] - $price[0];
echo "The product " . $names[$i] . " is " . $diff . " more expensive than " . $names[0];
}
}
This example make all comparision to the first product.
If you need all combination, it is a little more complexe, you have to make a double loop:
// Hard print the first product
echo "The product " . $names[0] . " is the cheapest";
// Make all possible comparisions
for($j = 0 ; $j < (count($names) - 1) ; $j++)
{
for($i = ($j+1) ; $i < count($names) ; $i++)
{
// calculate the diff between current product and first product
$diff = $price[$i] - $price[$j];
echo "The product " . $names[$i] . " is " . $diff . " more expensive than " . $names[$j];
}
}
// Hard print the last product
echo "The product " . $name[count($names) - 1] . " is the more expensive";

Adding up total of mysql_num_rows in a while loop

For example I have a mysql_num_rows results of 4,8,15,16,23,42 in a query that is inside a while loop of another query. My question is how can I total all the results inside that while loop? (Total of 133) Thanks.
EDIT:
How about if I want to get the percentage per each result of mysql_num_rows inside my while loop? Example: 4,8,15,16,23,42. Total is 108. $sum = 108. Percentage of 4 = 4/$sum = 3.7%, 8 = 8/$sum = 7.4% and so on..
Try something like this:
$Sum = 0;
while ($SomeInvariant)
{
mysql_query($SomeQuery);
$Sum += mysql_num_rows();
}
echo 'The sum is: ' . $Sum;
However, this approach is not very efficient (what if $SomeInvariant is true for many iterations, and your app has even more concurrent users?). To account for this, I would recommend restructuring your approach so the addition is done in SQL. This way, your query could look something like this: SELECT SUM(ColumnName) FROM ....
UPDATE: Addressing follow-up question in the comments
If you don't already have the sum available from the query, then you'll have to loop over the dataset twice. On the first pass, you'll calculate the sum. On the second pass, you'll calculate the ratio of each value to the sum.
For example:
$Sum = 0;
$Rows = array();
while ($SomeInvariant)
{
mysql_query($SomeQuery);
$Value = mysql_num_rows();
$Rows[] = $Value; // Push the value onto the row array
$Sum += $Value; // Add the value to the cumulative sum
}
echo 'The sum is: ' . $Sum;
foreach ($Rows as $Row)
{
echo $Row . '/' . $Sum . ' = ' . number_format($Row / $Sum) . '%';
}

Categories