Calculating total price from string value in php - php

I have a e-commerce shop and on the shopping cart page it gives me a separate price for every product, but I need total price.
in order to do that, I need to calculate all these values together and that's fine.
But, what bugs me is that I should calculate the sum of variables that are given in this format:
$455.00
What is the best way to extract the value "455" so I could add it to another value afterwards?
I hope I made myself clear...

Don't use float, but instead use an integer in cent. Floats are not precise (see Floating Point Precision), so the calculation tend to fail if you use floats. That's especially a burden if it is related to payments.
$str = '$455.00';
$r = sscanf($str, '$%d.%d', $dollar, $cent);
if ($r <> 2 or $cent > 99 or $cent < 0 or $dollar > 9999 or $dollar < 0) throw new Exception(sprintf('Invalid string "%s"', $str));
$amountInDollarCents = $dollar * 100 + $cent;
echo $str, ' -> ', $amountInDollarCents;
Demo

If you need only the dollar sign removed, use str_replace. To convert that to int or float, typecast it. However, using float results in non-exact calculations so be careful with it!
$newval = (int)str_replace('$', '', '$455.00');

I think that your ECommerce site only has $ (USD)
$price= substr($string_price,1);

This will convert your string to a float:
$price = (float)substr("$455.00", 1);
echo($price);
For more information, you can see this answer, which has a couple of good links for you in it.

What about the following:
$amount = array();
$amount[0] = '$455.15';
$amount[2] = '$85.75';
$total = 0;
foreach ($amount AS $value) {
$value = str_replace('$', '', $value);
$total += $value;
}
echo $total . "\n";
The cleaning operation is:
$value = str_replace('$', '', $value);
You might want to extract it in a function, especially if you need to use it in more than one place.
Another thing to think about is, why do you have the value in such way? It's a display format and such conversion should be the last to be done, ideally by the template. Maybe, if possible, you should consider to fix the code before, instead of applying a patch like this one.

It really looks like your program is doing it wrong. You should really represent all prices as (double) instead of a string. Then only when you need to show the price to the user you would prepend the $ sign to it, converting it to a string. But your program should really treat prices as numbers and not strings.
If you storing your price in the database as a string "$5.99" then you are really doing it wrong.

It's been a long time since I worked with PHP, so I don't know what the best practice would be for working with currency. One quick method would be to remove "$" and ".", and just add together the resulting as integers.
use str_replace() for instance, and replace "$" and "." with an empty string: http://se2.php.net/manual/en/function.str-replace.php
This will give you the whole sum in cents (thus avoiding some potential rounding problems). You can then divide it by 100 and format it however you like to display the sum as dollars.

Related

PHP lowest common denomination

I am working on a payment gateway and the amount parameter needs to formatted this way:
amount – (digits only) the integer value of the transaction in lowest common denomination (ex. $5.20 is 520)
I have already removed the $ and all values will be rounded to 2 decimal places.
In PHP if i try to cast amount as int ie (int)$amount I am going to loose the .20 in the example though its needed. What could be the best way to go about this?
You can multiply the amount by 100 and then convert it...
$amount = (int)($amount*100);
So 5.20 becomes 520.
If you are not sure about the number of decimal places, you could use regex to strip non-digital values from your string.
echo preg_replace('~\D+~', '', $amount);
\D means any non-numeric character. + means one or more.
If the value needs to be cast as an integer (rather than a string) write(int) just before preg_replace.
Of course, you could use str_replace() and target known characters like: $ and . (and - if it may exist).
After some feedback from the OP...
You can round and format in one step with number_format().
Code: ( Demo: https://3v4l.org/ir54s )
$amounts = array(0.001, 0.005, 5.20, 5.195, 5.204, 5);
foreach ($amounts as $amount) {
echo $amount , "->" , (int)number_format($amount, 2, '', '')."\n";
}
Output:
0.001->0
0.005->1
5.2->520
5.195->520
5.204->520
5->500

Mass Variable Decimal Places PHP

I know you can tell a variable to go to a certain number of decimal places using:
string number_format ( float $number [, int $decimals = 3 ] )
However, I cannot find a way of doing this en masse for all numbers. Since I have hundreds of variables, all of which need to have the same number of decimal places (whether it means rounding or extending zeros), I would like to be able to just tell it to automatically perform this command across the board instead of typing in the above command for all variables.
Does this function exist, or am I forced to type it all out the long way? Is there maybe a line in the .ini file that I could change if there is no command?
Thanks in advance.
I'm not storing these numbers in a database - I'm echo-ing them on the screen and sending an email.
(There is an equation going on from user input being generated by an HTML form).
The person receiving the email has asked that all numbers be rounded to the third decimal, whether that means rounding off at the thousandths or extending zeros to the thousandths if it only needed whole numbers, tenths, or hundredths. There are literally hundreds of individual variables, i.e. $number1, $number2, etc.
If you are talking about all numbers applied to string variables in your script you could run this line:
if(is_int($value) || is_float($value)){
$value = number_format ( float $number ,3 );
}
Obviously as you reference strings you can also run a similar query to check if your string is a floating numeric:
$values = get_defined_vars();
foreach ($values as $key=>$value){
if(is_string($value) && (float)$value == (string)$value){
$value = number_format ((float)$value , 3 );
}
/***
Save over the original script variables with the edited ones.
Note double dollar
***/
$$key = $value;
}
unset($values,$value,$key);
You could do with reading that in base-2 (computer storage) floating point numbers are inherently stored inaccurately, read http://floating-point-gui.de/ .
Also, really, why would you need this seemingly needless precision?
But then at what stage do you run this command, at the start of your script when the values are mostly empty? Or at the end when the values are mostly been used and no longer active?
I think my answer answers your question but I think that your question does not actually articulate your issue.
In response to the comment / edited qestion:
Simply rather than using $values = get_defined_vars(); use the values from saving the inputs into an array and doing foreach above through the array.
$values = array(array of numbers);
foreach ($values as &$value){
if(is_string($value) && (float)$value == (string)$value){
$value = number_format ((float)$value , 3 );
}
}
unset($value,$key);
This will update all values in the array to being of the spcified numerical placements.
You can use the decimal extension to achieve this, with a central place to create and format. Something like this:
class Number
{
public static function create($value, $precision = Decimal::DEFAULT_PRECISION): Decimal
{
return new Decimal($value, $precision);
}
public static function format(Decimal $decimal, int $places = 3): string
{
return $decimal->toFixed(3);
}
}

Can't get string numbers to become float or integer PHP

I'm trying to parse a csv file with PHP and everything works ok as long as I keep the numbers as strings. However, since I'd like to sum the values of nested arrays I need them to be numbers.
There are three values that I need to fix:
$column[1] is cost and contains decimals (ex. 20.30)
$column[2] is clicks (ex. 15)
$column[3] is conversions (ex. 3)
If I try using floatval() or intval() on the values they return 0.
Example: $cost = intval($column[1]);
I saw somewhere in another thread that they use trim() or ltrim() to clean up the value. So I tried that on my numbers...
$cost = intval(trim($column[1]));
$clicks = intval(trim($column[2]));
$conversions = intval(trim($column[3]));
But that just gives me the first digit of the number, so I get this..
cost : 2 (instead of 20.30)
clicks : 1 (instead of 15)
conversions: 3 (is actually correct)
I've tried using both "." and "," as decimals.
Really can't figure this one out. Any help I can get is much appreciated!
Structure:
array(4) {
[0]=> string(21)"avslag l�n"[1]=> string(11)"31.32"[2]=> string(3)"1"[3]=> string(5)"0 "
}
array(4) {
[0]=> string(45)"l�na trots kronofogden"[1]=> string(11)"99.12"[2]=> string(3)"2"[3]=> string(5)"0 "
}
array(4) {
[0]=> string(59)"g�r gymnasiet men vill ta l�n"[1]=> string(11)"33.86"[2]=> string(3)"1"[3]=> string(5)"0 "
}
array(4) {
[0]=> string(45)"l�n till enskild firma"[1]=> string(11)"80.07"[2]=> string(3)"1"[3]=> string(5)"1 "
}
You could type cast the values as follows:
$cost = (double) $column[1];
$clicks = (int) $column[2];
$conversions = (int) $column[3];
http://www.php.net/manual/en/language.types.type-juggling.php
if you are looking to format the double then do the following:
$cost = number_format($column[1], 2);
EDIT: Thanks for the var_dump, try this.
$cost = (double) $column[0][1];
$clicks = (int) $column[0][2];
$conversions = (int) $column[0][3];
You are trying to interact with a 2D array as if it was 1 dimensional.
use number format with floatval
$cost = floatval(column[1]);
$cost = number_format($cost, 2);
http://php.net/manual/en/function.number-format.php
if value of $column[1] is "20.30" you can simply use it for calculations as php automatically converts string to numbers when you do arthritic calculations.
ex:
$column[1]="20.30";//$column[1] is string.
$column[1]*=1.0;//Now $column[1] is an float variable..
You can also use type conversion like:
$a=(float)$column[1]*1;
And so on..
I could be wrong...in which case I have a gambling problem apparently...but I'm fairly certain you're trying to do all these conversions on an actual array(), not a string.
Your printout shows 4 different arrays, each with key/value pairs. And all of these are linked into $column.
If I had to guess, which I shouldn't do on Stack Exchange, I would say try this:
$column[1][1]
instead of what you have now as
$column[1]
I've been up quite a long time though so grain of salts are to be taken here.

PHP Convert number to currency

I've had a good look around for any help with my problem so hopefully someone can help me here.
Basically i have a number which is saved into a $price, the number is 15900. Which should translate to 159.00.
Does anyone know how to do this?
Use number_format for this. It will return a string, thereby keeping the decimal places intact, even if they will be .00.
$price = 15900;
// Defaults to a comma as a thousands separator
// but I've set it to an empty string (last argument)
$formatted = number_format( $price / 100, 2, '.', '' );
echo $formatted;
Or better still, maybe have a look at money_format as well, depending on whether internationalized notations and/or currency symbols are of importance as well.
$current = 15900;
$your = round($current / 100, 2);

PHP String to Float

I am not familiar with PHP at all and had a quick question.
I have 2 variables pricePerUnit and InvoicedUnits. Here's the code that is setting these to values:
$InvoicedUnits = ((string) $InvoiceLineItem->InvoicedUnits);
$pricePerUnit = ((string) $InvoiceLineItem->PricePerUnit);
If I output this, I get the correct values. Lets say 5000 invoiced units and 1.00 for price.
Now, I need to show the total amount spent. When I multiply these two together it doesn't work (as expected, these are strings).
But I have no clue how to parse/cast/convert variables in PHP.
What should I do?
$rootbeer = (float) $InvoicedUnits;
Should do it for you. Check out Type-Juggling. You should also read String conversion to Numbers.
You want the non-locale-aware floatval function:
float floatval ( mixed $var ) - Gets the float value of a string.
Example:
$string = '122.34343The';
$float = floatval($string);
echo $float; // 122.34343
Well, if user write 1,00,000 then floatvar will show error. So -
floatval(preg_replace("/[^-0-9\.]/","",$input));
This is much more reliable.
Usage :
$input = '1,03,24,23,434,500.6798633 this';
echo floatval(preg_replace("/[^-0-9\.]/","",$input));
Dealing with markup in floats is a non trivial task. In the English/American notation you format one thousand plus 46*10-2:
1,000.46
But in Germany you would change comma and point:
1.000,46
This makes it really hard guessing the right number in multi-language applications.
I strongly suggest using Zend_Measure of the Zend Framework for this task. This component will parse the string to a float by the users language.
you can follow this link to know more about How to convert a string/number into number/float/decimal in PHP.
HERE IS WHAT THIS LINK SAYS...
Method 1: Using number_format() Function. The number_format() function is used to convert a string into a number. It returns the formatted number on success otherwise it gives E_WARNING on failure.
$num = "1000.314";
//Convert string in number using
//number_format(), function
echo number_format($num), "\n";
//Convert string in number using
//number_format(), function
echo number_format($num, 2);
Method 2: Using type casting: Typecasting can directly convert a string into a float, double, or integer primitive type. This is the best way to convert a string into a number without any function.
// Number in string format
$num = "1000.314";
// Type cast using int
echo (int)$num, "\n";
// Type cast using float
echo (float)$num, "\n";
// Type cast using double
echo (double)$num;
Method 3: Using intval() and floatval() Function. The intval() and floatval() functions can also be used to convert the string into its corresponding integer and float values respectively.
// Number in string format
$num = "1000.314";
// intval() function to convert
// string into integer
echo intval($num), "\n";
// floatval() function to convert
// string to float
echo floatval($num);
Method 4: By adding 0 or by performing mathematical operations. The string number can also be converted into an integer or float by adding 0 with the string. In PHP, performing mathematical operations, the string is converted to an integer or float implicitly.
// Number into string format
$num = "1000.314";
// Performing mathematical operation
// to implicitly type conversion
echo $num + 0, "\n";
// Performing mathematical operation
// to implicitly type conversion
echo $num + 0.0, "\n";
// Performing mathematical operation
// to implicitly type conversion
echo $num + 0.1;
Use this function to cast a float value from any kind of text style:
function parseFloat($value) {
return floatval(preg_replace('#^([-]*[0-9\.,\' ]+?)((\.|,){1}([0-9-]{1,3}))*$#e', "str_replace(array('.', ',', \"'\", ' '), '', '\\1') . '.\\4'", $value));
}
This solution is not dependant on any locale settings. Thus for user input users can type float values in any way they like. This is really helpful e.g. when you have a project wich is in english only but people all over the world are using it and might not have in mind that the project wants a dot instead of a comma for float values.
You could throw javascript in the mix and fetch the browsers default settings but still many people set these values to english but still typing 1,25 instead of 1.25 (especially but not limited to the translation industry, research and IT)
I was running in to a problem with the standard way to do this:
$string = "one";
$float = (float)$string;
echo $float; : ( Prints 0 )
If there isn't a valid number, the parser shouldn't return a number, it should throw an error. (This is a condition I'm trying to catch in my code, YMMV)
To fix this I have done the following:
$string = "one";
$float = is_numeric($string) ? (float)$string : null;
echo $float; : ( Prints nothing )
Then before further processing the conversion, I can check and return an error if there wasn't a valid parse of the string.
For the sake of completeness, although this question is ancient, it's worth mentioning the filter_var() set of functions, which should not only handle the formatting bits itself, but also validate or sanitise the output, thus being safer to use in the context of a form being filled in by users (or, eventually, a database that might have some corrupted/inconsistent fields):
$InvoicedUnits = (float) filter_var($InvoiceLineItem->InvoicedUnits,
FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION));
$pricePerUnit = (float) filter_var($InvoiceLineItem->PricePerUnit,
FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION));
printf("The total is: %.2f\n", $InvoicedUnits * $pricePerUnit); // both are now floats and the result is a float, formatted to two digits after the decimal sign.
This sanitises the output (which will still remain a string) and will accept the current locale's setting of the decimal separator (e.g. dot vs. comma); also, there are more options on the PHP manual for validation (which will automatically convert the result to a float if valid). The results will be slightly different for different scenarios — e.g. if you know in advance that the $InvoiceLineItem will only have valid digits and symbols for floating-point numbers, or if you need to 'clean up' the field first, getting rid of whitespace, stray characters (such as currency symbols!), and so forth.
Finally, if you wish to have nicely-formatted output — since the total is expressed in a currency — you should also take a look at the built-in NumberFormatter class, and do something like:
$InvoicedUnits = (float) filter_var($InvoiceLineItem->InvoicedUnits,
FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION));
$pricePerUnit = (float) filter_var($InvoiceLineItem->PricePerUnit,
FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION));
$fmt = new NumberFormatter('de_DE', NumberFormatter::CURRENCY);
echo 'Total is: ' . $fmt->formatCurrency($InvoicedUnits * $pricePerUnit, 'EUR') . PHP_EOL;
This will also handle thousand separators (spaces, dots, commas...) according to the configured locale, and other similar fancy things.
Also, if you wish, you can use '' (the empty string) for the default locale string (set either by the server or optionally by the browser) and $fmt->getSymbol(NumberFormatter::INTL_CURRENCY_SYMBOL) to get the default 3-letter currency code (which might not be what you want, since usually prices are given in a specific currency — these functions do not take currency exchange rates into account!).
If you need to handle values that cannot be converted separately, you can use this method:
try {
// use + 0 if you are accounting in cents
$doubleValue = trim($stringThatMightBeNumeric) + 0.0;
} catch (\Throwable $th) {
// bail here if you need to
}

Categories