I have the follow code:
<?
$binary = "110000000000";
$hex = dechex(bindec($binary));
echo $hex;
?>
Which works fine, and I get a value of c00.
However, when I try to convert 000000010000 I get the value "10". What I actually want are all the leading zeros, so I can get "010" as the final result.
How do I do this?
EDIT: I should point out, the length of the binary number can vary. So $binary might be 00001000 which would result it 08.
You can do it very easily with sprintf:
// Get $hex as 3 hex digits with leading zeros if required.
$hex = sprintf('%03x', bindec($binary));
// Get $hex as 4 hex digits with leading zeros if required.
$hex = sprintf('%04x', bindec($binary));
To handle a variable number of bits in $binary:
$fmt = '%0' . ((strlen($binary) + 3) >> 2) . 'x';
$hex = sprintf($fmt, bindec($binary));
Use str_pad() for that:
// maximum number of chars is maximum number of words
// an integer consumes on your system
$maxchars = PHP_INT_SIZE * 2;
$hex = str_pad($hex, $maxchars, "0", STR_PAD_LEFT);
You can prepend the requisite number of leading zeroes with something such as:
$hex = str_repeat("0", floor(strspn($binary, "0") / 4)).$hex;
What does this do?
It finds out how many leading zeroes your binary string has with strspn.
It translates this to the number of leading zeroes you need on the hex representation. Whole groups of 4 leading zero bits need to be translated to one zero hex digit; any leftover zero bits are already encoded in the first nonzero hex digit of the output, so we use floor to cast them out.
It prepends that many zeroes to the result using str_repeat.
Note that if the number of input bits is not a multiple of 4 this might result in one less zero hex digit than expected. If that is a possibility you will need to adjust accordingly.
Related
This question already has answers here:
PHP and preg_match Regex to pull number with decimal out of string
(4 answers)
Closed 4 years ago.
I am trying to extract digits and decimal point from a string but the decimal point is lost when I am using following regular expression:
<?php
$str = "$40.0000";
echo $str;
echo "<br />";
$pattern = "/\D+/";
$str = preg_replace($pattern, '', $str);
echo $str;
?>
Output:
$40.0000
400000
I want to retain dot also. How to include dot in my regex?
<?php
$str = '$40000.00';
echo preg_replace('/[^\d.]/','',$str);
Several good answers here, too: How do I convert output of number_format back to numbers in PHP?
There are two appropriate functions for this purpose. The first, round(), rounds a value to a specified number of decimal places. The function’s first argument is the number to be rounded. This can be either a number or a variable with a number value. The second argument is optional; it represents the number of decimal places to round to. For example:
round (4.30); // 4
round (4.289, 2); // 4.29
$num = 236.26985;
round ($num); // 236
The other function you can use in this situation is number_format(). It works like round() in that it takes a number (or a variable with a numeric value) and an optional decimal specifier. This function has the added benefit of formatting the number with commas, the way it would commonly be written:
number_format (428.4959, 2); // 428.50
number_format (428, 2); // 428.00
number_format (123456789); // 123,456,789
I have a hex number that I get from a bin2hex() call. I need a string representing this number in the format outlined below:
$tmp = bin2hex($foo)
// $tmp is 0x123efd
I need some code that will give me the string "123efd".
It is a prefix of hexadecimal (0x). You need to remove the prefix with
$tmp = substr(bin2hex($foo), 2); // $tmp is 123efd
//assume that prefix is only 2 digits and you always remove the 2 digits
$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.
echo intval(chr(255));
I don't understand...
The chr() function turns a byte into its ASCII equivalent and intval() function gets the integer value of a variable.
If we were to break the statement into two different lines, this would be:
$a = chr(255); // $a is now a string
echo intval($a);
If you check intval()'s documentation you will notice that:
Strings will most likely return 0
although this depends on the leftmost
characters of the string. The common
rules of integer casting apply.
That's why the result is zero.
The byte 0xFF does not represent a digit in either octal, decimal or hexadecimal what intval is looking for. You probably wanted the ord function.
To output 255, you need:
echo intval(ord(chr(255)));
There are 128 ordinal numbers in ASCII, the 255 comes out to be ÿ so when you convert it to a number with intval, it will be 0.
Because chr delivers a string, in this case with just one character, the character 0xFF, or better known as ÿ.
intval on the other hand does a conversion from a string to an integer based on the content of the string, and not the characters.
echo intval("33"); // will print 33
echo intval("10", 8); // will print 8
echo intval("0xFF", 16); // will print 255
echo intval("m"); // will print zero...
//you can't convert letters like that to numbers.
chr(255)
returns a character corresponding to ASCI 255
and intval try to bring out integer part from a variable
since chr(255) returns a non-numeric character so intval get no int value and return 0
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?"