So I'm trying to understand this behaviour:
In my database table, I have a row quantity (int 11) and a column price (decimal 5,2).
Multiplying them to get a total, outputs an integer... how's this possible?
$qty = 2;
$price = 10;
$total = $qty * $price;
echo "$total";
// Outputs 20. Shouldn't it output 20,00?
So, for anyone else wondering, there's a php currency formatting function.
http://php.net/manual/it/function.money-format.php
Check the manual for further informations, thanks for the ones that answered.
You have not proven anything. 20 is the correct value.
$qty = 2;
$price = 10.23;
$total = $qty * $price;
echo "$total";
Gives 20.46, again the correct value.
If you want to format the output, use
printf("%.2f", $total);
to get results like
20.00
20.46
To adjust for locale, money_format() would be better. This would get you the , (or whatever) instead of .
Related
I'm trying to do some calculations on getting the total points used in a requested amount of money based on the amount per points.
Kindly refer to below code:
<?php
$amount_perpoints = bcdiv(622.9106666666667,1,2); // AMOUNT OF MONEY PER POINTS
$request_amount = 3114.55; //REQUESTED AMOUNT OF POINTS
$points = 0; // THIS WILL CONTAIN THE TOTAL POINTS
$total_amount = 0; // THIS WILL INCREMENT ACCORDING TO THE PRODUCT OF THE CURRENT POINT AND AMOUNT PER POINTS
while($total_amount < $request_amount){
$points = $points+0.50; //POINTS INCREMENTING BY 0.5
$total_amount = $points * $amount_perpoints;
}
echo $points;
?>
Output: 5.50
Above scenario outputs 5.50 but I believe it should only be 5.00. At 5.00 points of the iteration, $total_amount and $request_amount has already same value of 3114.55. Why does the while loop still satisfies even the two values of the comparing variables are not less than BUT EQUAL?
Your are comparing float numbers. Try to use
while (bccomp($total_amount, $request_amount) === -1) {
I think #jeff is right:
$amount_perpoints = bcdiv(622.9106666666667,1,2); // AMOUNT OF MONEY PER POINTS
$request_amount = 3114.55; //REQUESTED AMOUNT OF POINTS
$points = 0; // THIS WILL CONTAIN THE TOTAL POINTS
$total_amount = 0; // THIS WILL INCREMENT ACCORDING TO THE PRODUCT OF THE CURRENT POINT AND AMOUNT PER POINTS
while($total_amount <= $request_amount){
$points = $points+0.50; //POINTS INCREMENTING BY 0.5
$total_amount = $points * $amount_perpoints;
}
echo $points;
Since you count untill it reach the desired point it sould be less OR equal. It give the output of : 5.5
<?php
$amount_perpoints = bcdiv(622.9106666666667,1,2); // AMOUNT OF MONEY PER POINTS
$request_amount = 3114.55; //REQUESTED AMOUNT OF POINTS
$points = 0; // THIS WILL CONTAIN THE TOTAL POINTS
$new_points=0;
$total_amount = 0; // THIS WILL INCREMENT ACCORDING TO THE PRODUCT OF THE CURRENT POINT AND AMOUNT PER POINTS
while($total_amount < $request_amount){
$points=$new_points;
$new_points = $new_points+0.50; //POINTS INCREMENTING BY 0.5
$total_amount = $new_points * $amount_perpoints;
}
echo $points;
?>
Errors occur when calculating with fractional fractions as a float. Float cannot represent certain decimal numbers exactly. Use only the BC Math functions for such calculations. You don't need a loop either.
$amount_perpoints = "622.91"; // AMOUNT OF MONEY PER POINTS
$request_amount = "3114.55"; //REQUESTED AMOUNT OF POINTS for result 5.0
//$request_amount = "3426.005"; //REQUESTED AMOUNT OF POINTS for result 5.5
$point_step = "0.50";
//calculation
$points = bcdiv($request_amount,$point_step,2);
$points = bcdiv($points,$amount_perpoints,0);
$points = bcmul($points,$point_step,1);
//output
var_dump($points); //string(3) "5.0"
UPDATE - the problem was actually completely out of the rounding function. It seems as though $price (used in woo commerce) is a string and for some reason I can't use it in a calculation. If I simply return $price, no problem. All of this was fine when I was simply returning the value of the other function.
function xa_only_sale_price($price, $product)
{
error_log ("price in the beginning is " . $price);
if(!is_cart() && !is_checkout() && !is_ajax()){
if ($product->is_type('simple') || $product->is_type('variation')) {
$price = regularPriceHTML_for_simple_and_variation_product($price, $product);
$val = (float)$price;
error_log( "ceiling = " . ceil($val* 2) / 2); // 0 printed to log
return ceil($val* 2) / 2; this returns 0
// return roundNum(regularPriceHTML_for_simple_and_variation_product($price, $product));
}
}
error_log ("price before call is " . $price); // this returns 0
// return roundNum($price); //this is never in use
}
--------------- original post-----------------------------
I am new to php - thank you for all of the help in advance. I am assuming that this issue has something to do with data types but I haven't been able to figure this one out.
In this example $num is the price of a woocommerce product. If I simply return $num I see the price that I am expecting to see. I am simply trying to round the value in this function (I simplified the function for the sake of the question).
function roundNum($num){
$nearest = 0.50;
return ($num / $nearest) ;
This returns 0 to the browser. However, forcing the value of $num results in a valid calculation and return.
function roundNum($num){
$num = 100.0;
$nearest = 0.50;
return ($num / $nearest) ;
The simplest solution is to typecast your input. A small example in your case is:
function roundNum($num){
$nearest = 0.50;
$result = (float) $num/ (float) $nearest;
return $result;
}
Read more about typecasting here
EDIT:
As it turns out your $num is a string. You can change this to a type float and make your calculations, like so:
$num = "48.2";
$float = (float)$num;
echo ceil($float * 2) / 2;
In this example your number is always rounded up by 0.5, so in this case to 48.5
Demo
I have just coded a basket/cart system for my websitye but I am sturggling on getting the total cost for items in the basket? I have the price for each item (i loop basket items in a loop) what the main question here is how can I add money strings together and get a valid money string total amount like below...
£4.56 +
£2.35 +
£3.00
= £9.91
£2.83 +
£19.83 +
£22
= £44.66 (I think)
you need to remove tha '£' from each item and then convert it to a integer then you create a variable named sum and in a loop you add each element to the sum , there you are the algorithm :
int sum = 0;
for_each (item i in basket)
{
string tmp = i.get_price() ; // get_price returns "£x" string
sum += to_integer(tmp.sub_str(1,tmp.length()-1));
/* copy from the pos 1 to the end ignoring the '£'*/
}
then the sum variable contains what you want :D
Use a number formatter:
$f = new NumberFormatter("en-GB",NumberFormatter::CURRENCY); //Make sure you use the correct locale
$total = 0;
foreach ($arrayOfCurrencies as $number) {
$c = $p = null;
$total += $f->parseCurrency($number, $c, $p);
}
return $f->formatCurrency($total,$c);
Don't use things like substring for this when there's built-in ways to do it.
I have an array of value series like:
$series = [100,300,500,800,1000,3000,5000,10000,15000,20000];
Another value getting from DB like:
$point = $data[‘earned_point’];
I need the highest match from the series. such as I got a value from db (1500) the highest match of the value is 1000 in the series, so I need to get the $series[4] and make it
$reward = $series[4] * 0.1;
I'll run it in a loop to do it for all the values got from DB.
I'm posting alternate code as the accepted answer while is correct can be very inefficient if you are working with a large array.
<?php
function computeReward($series, $point, $percent = 0.1){
arsort($series); // sort the series in reverse so we can pass any array and the highest number will be the first because we are looking for a number lower or equal to our point
foreach($series as $min_point){
if($min_point <= $point){
return $min_point * $percent; // return the min_point * the percentage, this stops the loop there for being more efficient
}
}
}
$series = [100,300,500,800,1000,3000,5000,10000,15000,20000];
$point = $data['earned_point'];
$reward = computeReward($series, $point);
?>
Do you mean you want to get which highest $series item is equal or less than $point ?
<?php
$series = [100,300,500,800,1000,3000,5000,10000,15000,20000];
$point = $data['earned_point'];
foreach ($series as $min_point) {
if ($point >= $min_point) {
$matched_min_point = $min_point;
}
}
$reward = $matched_min_point*0.1;
Let me know if this works for you
I'm trying to add some numbers in a foreach loop in my PHP code. I am getting a percentage of numbers in a while loop in my MySQL query for each result that I get in my PHP page.
All I need to do is to add up the final values in and show them as total.
This is how I make up the percentage in my while loop in my MySQL query:
$percentage = 10;
$totalWidth = $fees;
$new_width = ($percentage / 100) * $totalWidth;
The $fees value is dynamic and it is different for each result in my while loop. the code above works as it should.
Now I want to add up all the values of $new_width. For example:
If one result's $new_width is 25 and the other one is 10 and another one is 5, I need to do this: $total = 25 + 10 + 5;
So I tried something like this:
$total = 0;
foreach($new_width as $var) {
$total = $var + $var;
}
echo $total;
but the above code doesn't really make sense and it won't do anything at all.
Could someone please advise on this matter?
First you want to change this line in your while loop so you get an array:
$new_width = ($percentage / 100) * $totalWidth;
to this:
//Declare it as an array before your while loop
$new_width = array();
//In your while loop
$new_width[] = ($percentage / 100) * $totalWidth;
//^^ See here
After this you just have to change the line in your foreach loop like this:
$total = $var + $var;
to this:
$total += $var;
(If you want you also can do this in your while loop)
If you have an array of numbers and you want to calculate the sum of those numbers, you should use array_sum().
According to the logic, you are setting the total to 2 X $var.
My answer is very similar, but you add it to the total which is outside of the loop and the value will keep growing:
$total = 0;
foreach($new_width as $var) {
$total += $var;
}
echo $total;
Or simply as stated before, if it is the only value in the array:
$total = array_sum($new_width);