$value = preg_replace("/[^0-9]+/", '', $value);
How could I edit this regex to get rid of everything after the decimal point? There may or may not be a decimal point.
Currently "100.1" becomes 1001 but it should be 100.
Complete function:
function intfix($value)
{
$value = preg_replace("/[^0-9]+/", '', $value);
$value = trim($value);
return $value + 0;
}
It is used to format user input for numbers as well as servers output to format numbers for the DB. The functions deals with very large numbers, so I can't use intval or similar. Any extra comments to improve this function are welcome.
You could just change the regex to /[^0-9].*/s.
.* matches zero or more characters, so the first character that is not a digit, and the digits that immediately follow, would be deleted.
You need to have a pattern that starts the search with a decimal place. At the moment you're only deleting the . not the numbers after it... So you could do '/\.[\d]+/'
$text = "1201.21 12 .12 12.21";
$text = preg_replace('/\.[\d]+/', '' ,$text);
The above code would result in $text = "1201 12 12"
Why not $value = round($value, 0);? This can handle large values and is meant to get rid of the following decimals mathematically (I'd rather work with numbers as numbers not as strings). You can pass PHP_ROUND_HALF_DOWN as a third parameter if you want to just get rid of the decimals 10.7 -> 10. Or floor($value); could work too.
Related
I have phone numbers that I want to format
And I have a pattern matcher that breaks down the numbers into a 10 digit format, and then applies dashes.
It works most of the time. However Im having an issue with certain numbers.
$trimmed = trim(preg_replace('/\s+/', '', $v->cust_num));
$tendigit = str_replace(array( '(', ')','-',' ' ), '', $trimmed);
$num = substr($tendigit,0,3)."-".substr($tendigit,3,3)."-".substr($tendigit,6,4);
This will change (555)555 5555, or 555-555 5555 or 5555555555 or (555)-555-5555 or 555-555-5555
to my format of 555-555-5555
However, I came across a few entries in my database, that dont seem to want to change.
One of the bad entries is this one. It contains two white spaces infront of the 4.
4-035-0100
When it runs through $trimmed, and I output $tendigit...it outputs
40350100
as expected. But then when I apply $num to it. It goes back to
4-035-0100
I would at least expect it to be
403-501-00
It seems there is some hidden whitespace in it, that my preg_replace, trim, and str_replace are not attacking.
Any ideas??
Thanks
The code below works, I have tried it with the special characters we discovered in the comments. Basically, the regex removes everything that isnt a number (0-9) and then uses your original formatting.
$trimmed = preg_replace('/\D+/', '', $v->cust_num);
$num = substr($trimmed,0,3)."-".substr($trimmed,3,3)."-".substr($trimmed,6,4);
You can condense your code a little:
$tendigit = preg_replace('/[^\d]/', '', $v->cust_num);
$num = substr($tendigit,0,3)."-".substr($tendigit,3,3)."-".substr($tendigit,6,4);
Though, you should add in some conditions to check that the phone number actually has 10 digits too:
$tendigit = preg_replace('/[^\d]/', '', $v->cust_num);
if(strlen($tendigit == 10)){
$num = substr($tendigit,0,3)."-".substr($tendigit,3,3)."-".substr($tendigit,6,4);
} else {
// catch your error here, eg 'please enter 10 digits'
}
The first line removes any 'non-digit' [^\d].
The conditional statement checks if the $tendigit variable has 10 digits in it.
If it does, then it uses your code to parse and format.
If it doesnt, then you can catch an error.
I am trying to write a regular expression such that if a number have decimal point then the zeros (0) at the end must be removed.
Example:
$value = 234.8076000
After Regexp Replace it should become
234.8076
I am trying the following regexp [0]+$ in preg_replace but the problem is that if the value does not have decimal point and it contain zero at the end then that zero is also removed.
Example:
$value = 2340
It becomes 234 but it should remain 2340
Any idea? Is there any in-built function in php that can do this?
Yes, you really can do it with regex:
$pattern = '/(\.\d*[^0])0+$/';
echo preg_replace($pattern, '$1', '2340'); // 2340
echo preg_replace($pattern, '$1', '2340.0'); // 2340.0
echo preg_replace($pattern, '$1', '2340.07600'); // 2340.076
... but the simplest way is just convert a string value into a float value.
echo (float)'2340'; // 2340
echo (float)'2340.0'; // 2340
echo (float)'2340.07600'; // 2340.076
Echoing floats that are really integer values drops the decimal part apparently - but it seems from your comments it's actually what you want.
You can do it without regexpes:
php > echo ((float)"21.40200")."\n";
21.402
/(\.\d*?)0+$/, works except /\d+\.0{n}/ cases
I have encountered a strange IP which has redundant zero values among the octets. Is there anyway to properly validate this as an IP or use regular expression to remove those redundant zeroes?
example is of follows:
218.064.215.239 (take note of the extra zero at the second octet "064").
I do have one working IP validation function but it will not validiate this Ip properly due to the nature of the regular expression unable to accept that extra zero. Following is the code in PHP:
function valid_ip($ip) {
return preg_match("/^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])" .
"(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/", $ip);
}
thanks for any help in advance peeps! :D
This will correct them:
$ip = "123.456.007.89";
$octets = explode(".", $ip);
$corrected = array();
foreach ($octets as $octet) {
array_push($corrected, (int)$octet);
}
echo implode(".", $corrected);
You have to accept the zero like this:
^(0?[1-9]|0?[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.(0?[0-9]|0?[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$
Play with this regular expression on rubular.com.
The 0? I added matches zero or one occurence of 0. So 0?[1-9][0-9] for example matches both 010 and 10 for example.
Change the bare |1 occurrences to |[01]. Are you sure this is not supposed to be interpreted as an octal number, though? Some resolvers do that.
Use ip2long().
You should figure out where those extra zeroes are coming from. Those leading zeroes can't be just dropped. On most platforms they mean that the octet is in octal form instead of decimal. That is: 064 octal equals 52 decimal.
Did you have a go yourself? It's really quite simple.
|1[0-9][0-9]| matches 100-199, as you are now wanting to match 000-199 (as above that it is 200-155) you just need to make a set for the 1 to be 1 or 0.
function valid_ip($ip) {
return preg_match("/^([1-9]|[1-9][0-9]|[01][0-9][0-9]|2[0-4][0-9]|25[0-5])".
"(\.([0-9]|[1-9][0-9]|[01][0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/", $ip);
}
And that can be refactored down (allowing leading zeroes) to:
function valid_ip($ip) {
return preg_match("/^([01]?[0-9]{1,2}|2[0-4][0-9]|25[0-5])".
"(\.([01]?[0-9]{1,2}|2[0-4][0-9]|25[0-5])){3}$/", $ip);
}
Or to strip these unneeded zeros:
function strip_ip($ip) {
return preg_replace( '/0+([^0])(\.|$)/' , '$1$2' , $ip );
}
So I have done a fair bit of research on how to store "money" in a database and I think the system I want to use is
Converting Money into CENTS and then storing the CENTS in a MySQL DB with a field type of DECIMAL (19,4).
My question is, IF I have an input field from the user... how do I deal with multiple input types.
IE:
$input = "1,346.54"
$input = "10,985.23"
$input = "110,400.50"
$input = "1033.44"
etc etc...
What would be the best method for converting this to CENTS? As we have to deal with 'strings' and convert them to INT, and divide by 100... Everything that I try throws issues because of the "comma" separation with the numbers.
Any thoughts or direction would be greatly appreciated.
function getMoneyAsCents($value)
{
// strip out commas
$value = preg_replace("/\,/i","",$value);
// strip out all but numbers, dash, and dot
$value = preg_replace("/([^0-9\.\-])/i","",$value);
// make sure we are dealing with a proper number now, no +.4393 or 3...304 or 76.5895,94
if (!is_numeric($value))
{
return 0.00;
}
// convert to a float explicitly
$value = (float)$value;
return round($value,2)*100;
}
Looks like there is a NumberFormatter class which provides a parseCurrency method. Have a look at http://www.php.net/manual/en/numberformatter.parsecurrency.php
The example provided is
$fmt = new NumberFormatter( 'de_DE', NumberFormatter::CURRENCY );
$num = "1.234.567,89 $";
echo "We have ".$fmt->parseCurrency($num, $curr)." in $curr\n";
You can remove the commas like this:
$input = str_replace( ',', '', $input);
At this point, you can convert to cents by converting to a float and multiplying by 100. However, this is probably unnecessary. You would potential encounter precision issues when performing math operations, but simply storing the values in the database can be done in the original form without alteration of the value (assuming your DB tables are properly structured):
$input = (float)str_replace( ',', '', $input);
function convert_to_cents($v)
{
$v = str_replace(',','',$v);
$p = explode('.',$v);
if(strlen($p[1])<2){ $p[1] = $p[1]*10;}
return ($p[0]*100)+$p[1];
}
This converts most of the decimal currencies to their subunits.
$1,234,567.89 = 123456789
£ 1,234,567.89 = 123456789
€1.234.567,89 = 123456789
12,34 EUR = 1234
12,34 € = 1234
12,30 € = 1230
1,2 = 102
function convertDecimalCurrencyToSubUnit($str)
{
if( preg_match('/^(.+)[^\d](\d|\d\d)[^\d]*$/', $str, $m) )
return intval(preg_replace('/[^\d]/', '', $m[1]) . ( (strlen($m[2])>1) ? $m[2] : ('0' . $m[2]) ));
return 0;
}
Probably just remove the ',' and the '.' from the string, the result is the amount in cents.
You will probably need to parse the string from the back using strrpos ... If you find a comma 2 spots from the end, then its prob safe to assume its foreign currency and those are the CENTS... Once you determine that, use a regex to strip the remaining commas (after you convert the "CENTS" comma to a decimal of course) ... Now you have a normal DEC number to play with.
Use this to find the last comma in your string ... strrpos
Use this to replace the commas preg_replace
Here is a helpful regex website .. regexlib
//Finding the last comma
$yourCommaPos = strrpos($myString, ',');
if ($yourCommaPos == strlen($myString) - 2) {
//Comma is foreign currency decimal
// Replace with '.'
} else {
//Not foreign Currency so...
//Strip Commas
preg_replace(',', '', $myString);
}
I have a form in which people will be entering dollar values.
Possible inputs:
$999,999,999.99
999,999,999.99
999999999
99,999
$99,999
The user can enter a dollar value however they wish. I want to read the inputs as doubles so I can total them.
I tried just typecasting the strings to doubles but that didn't work. Total just equals 50 when it is output:
$string1 = "$50,000";
$string2 = "$50000";
$string3 = "50,000";
$total = (double)$string1 + (double)$string2 + (double)$string3;
echo $total;
A regex won't convert your string into a number. I would suggest that you use a regex to validate the field (confirm that it fits one of your allowed formats), and then just loop over the string, discarding all non-digit and non-period characters. If you don't care about validation, you could skip the first step. The second step will still strip it down to digits and periods only.
By the way, you cannot safely use floats when calculating currency values. You will lose precision, and very possibly end up with totals that do not exactly match the inputs.
Update: Here are two functions you could use to verify your input and to convert it into a decimal-point representation.
function validateCurrency($string)
{
return preg_match('/^\$?(\d{1,3})(,\d{3})*(.\d{2})?$/', $string) ||
preg_match('/^\$?\d+(.\d{2})?$/', $string);
}
function makeCurrency($string)
{
$newstring = "";
$array = str_split($string);
foreach($array as $char)
{
if (($char >= '0' && $char <= '9') || $char == '.')
{
$newstring .= $char;
}
}
return $newstring;
}
The first function will match the bulk of currency formats you can expect "$99", "99,999.00", etc. It will not match ".00" or "99.", nor will it match most European-style numbers (99.999,00). Use this on your original string to verify that it is a valid currency string.
The second function will just strip out everything except digits and decimal points. Note that by itself it may still return invalid strings (e.g. "", "....", and "abc" come out as "", "....", and ""). Use this to eliminate extraneous commas once the string is validated, or possibly use this by itself if you want to skip validation.
You don't ever want to represent monetary values as floats!
For example, take the following (seemingly straight forward) code:
$x = 1.0;
for ($ii=0; $ii < 10; $ii++) {
$x = $x - .1;
}
var_dump($x);
You might assume that it would produce the value zero, but that is not the case. Since $x is a floating point, it actually ends up being a tiny bit more than zero (1.38777878078E-16), which isn't a big deal in itself, but it means that comparing the value with another value isn't guaranteed to be correct. For example $x == 0 would produce false.
http://p2p.wrox.com/topic.asp?TOPIC_ID=3099
goes through it step by step
[edit] typical...the site seems to be down now... :(
not a one liner, but if you strip out the ','s you can do: (this is pseudocode)
m/^\$?(\d+)(?:\.(\d\d))?$/
$value = $1 + $2/100;
That allows $9.99 but not $9. or $9.9 and fails to complain about missplaced thousands separators (bug or feature?)
There is a potential 'locality' issue here because you are assuming that thousands are done with ',' and cents as '.' but in europe it is opposite (e.g. 1.000,99)
I recommend not to use a float for storing currency values. You can get rounding errors if the sum gets large. (Ok, if it gets very large.)
Better use an integer variable with a large enough range, and store the input in cents, not dollars.
I belive that you can accomplish this with printf, which is similar to the c function of the same name. its parameters can be somewhat esoteric though. you can also use php's number_format function
Assuming that you are getting real money values, you could simply strip characters that are not digits or the decimal point:
(pseudocode)
newnumber = replace(oldnumber, /[^0-9.]/, //)
Now you can convert using something like
double(newnumber)
However, this will not take care of strings such as "5.6.3" and other such non-money strings. Which raises the question, "Do you need to handle badly formatted strings?"