number_format in a number_format doesn't work - php

I'm having trouble with a tiny code in php:
$price = 135;
$price_sale = number_format($price * 0.75,2,',','');
//*returns 101,25 *//
$count_products = 3;
$new_price = number_format($price_sale * $count_products,2,',','');
//* returns 303,00 and not 303,75 *//
How can I fix this problem?
Regards,
Frank

Keep numbers as numbers. Don't format until the output stage.

Never do number_format on numbers you want to do calculations with.
101,25 is not a valid number in PHP.
Work with the raw values until the number is output. Then, do a number_format().

use:
$new_price = number_format($price * 0.75 * $count_products,2,',','');
as $price_sale is a string and won't probably have the value you're calculating with, after type casting. (See: http://php.net/manual/de/language.types.type-juggling.php)

Related

What is the best way to move decimal point in PHP

I'm working on project where you can make payments with credit card.
I have booking system from what I get "price" and then it sends this price to merchant online payment page.
My problem is that booking system sends price in decimal. Like 123.45.
But merchant accepts only this format: 12345. And after receiving this format it ads decimal point automatically.
I need to convert this "price" without decimal point. In other words move it to right. What is the best function or solution to do that?
For now I'm using round() function and add two zeros (00). But this way is only if I really use rounded up prices.
$price = $_POST['price'];
$price = round($price) . '00';
I expect the output 123.45 to be 12345. Other example 123.00 to be 12300.
Careful... you may lose precision. I had to switch to using bcmul()
$version=22.0220;
$int1=(int)($version*10000); // $int1 is 220219 (oops)
$int2=(int)(bcmul($version,10000)); // $int2 is 220220 (correct)
<?php
$withoutDecimal = $withDecimal * 100;
?>
For those who need more flexible solution. For example, Bitcoin has 8 decimal places, US dollar - 2
function price_minor_units($dollars, $decimals = 2)
{
return $dollars * (10 ** $decimals);
}
function price_major_units($cents, $decimals = 2){
return $cents / (10 ** $decimals);
}

Php ignores decimals while adding two numbers

When adding two number it ignores the decimals, in database the product_price and product_shipping_cost data type is decimal(10,2)
$product_price = 272.70; $product_price = 189.00;
$product_shipping_cost 14.00;
The total should be 475.70 but i get 475.7 as the output how do i fix this i have tried adding (float) but still same
foreach($mycart as $row_checker){
$CKItemSubtotal += (float)(($row_checker->product_discount>0) ? $row_checker->product_price * ((100-$row_checker->product_discount) / 100) * $row_checker->cart_qty : $row_checker->product_price * $row_checker->cart_qty) + $row_checker->product_shipping_cost;
}
Please can anyone help me
number_format($number, 2)
If two parameters are given, number will be formatted with decimals decimals with a dot (".") in front, and a comma (",") between every group of thousands.
You may also format number using printf. In your case: printf('%.2f', 475.7);, but that's up to you.

PHP calculation logic issue

Not sure if I'm being stupid here. Probably something obvious but when you've been staring at the same issue for hours on end it starts to drive you crazy.
I'm doing a few calcuations using PHP, all fairly straight forward.
I have a table called sales, say:
total, costs
424.53, 125
853.91, 125
To get the data I need...
gross = total - cost
vat = gross - ( gross / 1.2 )
profit = gross - vat
I need to generate a report, so for each row in the sales database I need to loop over and run the above calculations to get the data I need.
If I add the sum of total and the sum of costs, and then work out the gross, vat and profit above, and round vat and profit to 2 decimal plates the values are as expected.
The problem I'm having is where I'm looping over each row and calculating gross, vat and profit. If I don't round vat and profit on each row, but round the final totals, they match the values where I add sum(total) and sum(costs).
But then in the report I generate, if I don't round vat and profit then they don't show to two decimal places, which I need.
Actual code is below, pretty sure it's more of a logic issue than code.
$sum = 0; // Test variable
foreach( .. as ... )
{
// Assigning $total and $cost
$gross = $total - $cost;
$data['profit'] = $gross;
// If I round this VAT so vat shows to two decimal points, $sum becomes off by some pence.
// If I don't round it but then round $sum after the loop, it matches the echo statement value which is the correct amount
$vat = $this->vat( $gross );
$data['vat'] = $vat;
$profit = $gross - $vat;
$data['net_profit'] = $profit;
$sum += $profit;
$array[] = $data;
}
echo "131547.82<br><br>";
echo $sum;
die;
It's an accuracy problem caused by using floats.
When you do calculations with pure PHP you need to be careful.
You may run into glitches, when comparing two floats.
I would suggest to use some helper function or a currency / money object in order to work with them. It might be better to use a PHP Extension for math stuff, like the PHP Extensions BCMath, which has for instance the function bcadd(). Anyway, here are some helpers, which you might use in your calculation loop.
/**
* turn "string float" into "rounded float with precision 2"
* (string) 123,19124124 = (float) 123.19
*
* #param type $string
*/
function formatNumber($string, $precision = 2)
{
return round((float) str_replace(',', '.', $string), $precision);
}
There is also sprintf: echo sprintf("%.2f", $a);.
These two are based on PHP's NumberFormatter from the Intl Extension.
// 123,19 EUR = 123.19
function parseNumber($string_number)
{
$fmt = numfmt_create('de_DE', \NumberFormatter::DECIMAL);
return numfmt_parse($fmt, $string_number);
}
// 123.19 = 123,19 EUR
function numberFormat($value)
{
$f = \NumberFormatter::create("de_DE", \NumberFormatter::CURRENCY);
return $f->formatCurrency($value, 'EUR');
}
For comparing two floats:
/**
* Do not check, that the numbers are exactly the same,
* but check that their difference is very small!
* A really small rounding error margin (epsilon) is expected.
* It's an equals check within defined precision.
*/
function compareFloats($a, $b)
{
return (abs(($a - $b) / $b) < 0.000001) ? true : false;
}

Convert string to integer and multiply two integers

I have a big time trying to either convert a string into a integer or multiply two integers. I can't convert the string into integer because it's resulting me into a boolean (when I'm using var_dump). I can convert the other integer in string, but I'm unable to multiply it.
I have this:
<? $fees=$commerce->cart->get_total();
$payfee = str_replace(' €', '', $fees);
$payfee = str_replace(',','', $payfee); //this is the string
$fee = 0.025;
$paypal = $payfee * $fee; //this thing is not working
?>
I tried converting the payfee in integer, but still can't make it work. I did something like this before and worked well, but not this time.
Any help will be appreciated.
P.S Thank you to the whole stackoverflow.com community which helped me many times before.
OP is running WooCommerce, and his $commerce->cart->get_total();
function responds output such as <span class="amount">560 €</span> (560 €)
and he's asking how to convert this to a number so he can get a fee
(2.5 %) from the amount.
First of all, the problem here is that the get_total() function responds with a string.
The correct way to fix this string would be a simple example such as
<?php
$totalAmountString = $commerce->cart->get_total(); //<span class="amount">560 €</span>
$totalAmountString = strip_tags($totalAmountString); //get rid of the span - we're left with "560 €"
$totalAmountString = str_replace(array(" €", ","), "", $totalAmountString);
$totalAmountFloat = (float)$totalAmountString;
$fee = 0.025;
$feeForThisAmount = $totalAmountFloat * $fee;
var_dump($feeForThisAmount);
$totalAmountWithFee = $totalAmountFloat + $feeForThisAmount;
var_dump($totalAmountWithFee);
?>
However, according to the Woo Commerce API Documentation you should be able to use $commerce->cart->total to get a float of the number, so a solution that might also work (again, I know nothing about WooCommerce), would be the following:
<?php
$totalAmountFloat = $commerce->cart->total;
$fee = 0.025;
$feeForThisAmount = $totalAmountFloat * $fee;
var_dump($feeForThisAmount);
$totalAmountWithFee = $totalAmountFloat + $feeForThisAmount;
var_dump($totalAmountWithFee);
?>
Edit
According to your latest data dump, the problem is that you're using
$paypal_fees=$woocommerce->cart->get_total() * 0.025;
where you should be using
$paypal_fees=$woocommerce->cart->total * 0.025;
as ->get_total() receives a string, and ->total receives a float.
try this
$integer =(int)$string;
LIve example
with var_dump() its correct
check this link
Use type casting like
$integer = (int)$myString;
then you can convert it to an integer,and its become easy to multiply
Use intval() function to covert string to integer
intval
From your elementary school technique based algorithm is posted here . You need not to convert string to integer in this case

PHP: string with decimals strips decimals when converting to float

With the function floatval() I try to convert a string with decimals to a float, but it doesn´t give me the desired result. Here´s the code:
$price_calc = str_replace(',','.',$price);
$reduction_calc = str_replace(',','',$reduction);
$reduction_calc = '1.'.$reduction;
$price_calc = floatval($price_calc);
$reduction_calc = floatval($reduction_calc);
$oldprice = $price_calc * $reduction_calc;
This chunk of code is from a scraper I´m building that fetches the price ($price) and the percentage of reduction($reduction). From that price and reduction I´m trying to calculate the old price.
Before being able to make the calculation I have to convert both $price and $reduction to float. That´s where it goes wrong
The problem is that for example when $reduction is 51 for example, the value $reduction_calc should be 1.51 . For some weird reason after applying the floatval() the variable $reduction_calc turns into 1.
Anybody out there who has an idea why? Thanks in advance!
Try this:
$reduction_calc = floatval($reduction_calc);
You probably have leading/trailing spaces in your $reduction or $price strings
Add this code before your script
$reduction = trim($reduction);
$price = trim($price);

Categories