Bitwise and in PHP - php

I am very new face to PHP. I read that dechex(255) will give the corresponding hex value ff in PHP.
I need the hex value of -105. I tried dechex(-105) and got the result as ffffff97. But I just only want 97 to do some kind of stuffs.
In Java I know that a bit wise operation with 0xff gave us the result 97 that is (byte)-105 & (byte)0xff = 0x97.
Please to find the solution in PHP just like I've done in Java.

You can do it in php like this:
var_dump(dechex(-105 & 255))
to make it out of the final byte (example output below)
string(2) "97"

dechex() gives you a hexadecimal value for a decimal value between 0 and 2*PHP_INT_MAX+1 (unsigned int).
Anything below 0 or above 2*PHP_INT_MAX+1, will loop.
-105 is NOT 0xffffff97 , and it is not 0x97
0xffffff97 is 4294967191.
and 0x97 is 151.
If you want the hexadecimal representation of the negative number turned into a positive number, use the function abs().
$abs = abs(-105); // $abs becomes +105
$hex = dechex($abs); // $hex becomes 69

Either you want a binary negative value (ffffff97) or a signed value
// for a signed value
$i = -105;
if($i < 0)
echo '-'.dechex(abs($i));
else echo dechex($i);
If you want to remove front "f"
echo preg_replace('#^f+#', '', dechex($i));

Related

Get negative numbers after conversion to float [duplicate]

I am trying to convert a hex string into a signed integer.
I am able to easily transfer it into an unsigned value with hexdec() but this does not give a signed value.
Edit:
code in VB - the two "AA" hex values are representative.
Dim bs(2) As Byte
bs(1) = "AA"
bs(2) = "AA"
Dim s As Short
s = BitConverter.ToInt16(bs, 1)
Check out this comment via php.net:
hexdec() returns unsigned integers. For example hexdec("FFFFFFFE") returns 4294967294, not -2. To convert to signed 32-bit integer you may do:
<?php
echo reset(unpack("l", pack("l", hexdec("FFFFFFFE"))));
?>
As said on the hexdec manual page :
The function can now convert values
that are to big for the platforms
integer type, it will return the value
as float instead in that case.
If you want to get some kind of big integer (not float), you'll need it stored inside a string... This might be possible using BC Math functions.
For instance, if you look in the comments of the hexdec manual page, you'll find this note
If you adapt that function a bit, to avoid a notice, you'll get :
function bchexdec($hex)
{
$dec = 0;
$len = strlen($hex);
for ($i = 1; $i <= $len; $i++) {
$dec = bcadd($dec, bcmul(strval(hexdec($hex[$i - 1])), bcpow('16', strval($len - $i))));
}
return $dec;
}
(This function has be copied from the note I linked to ; and only a bit adapted by me)
And using it on your number :
$h = 'D5CE3E462533364B';
$f = bchexdec($h);
var_dump($f);
The output will be :
string '15406319846273791563' (length=20)
So, not the kind of big float you had ; and seems OK with what you are expecting :
Result from calc.exe =
15406319846273791563
Hope this help ;-)
And, yes, user notes on the PHP documentation are sometimes a real gold mine ;-)
I've been trying to find a decent answer to this question and so I wrote this function which works well for a Hex string input, returning a signed decimal value.
public function hex_to_signed_int($hex_str){
$dec = hexdec($hex_str);
//test is value negative
if($dec & pow(16,strlen($hex_str))/2 ){ return $dec-pow(16,strlen($hex_str));}
return $dec;
}

Convert IEEE754 to hex in PHP

For a project I need to read in information from MQTT. The payload is filled with protobuf information, that needs to be converted.
For a certain value I receive 5.6904566139035E-28 as float. Using http://www.exploringbinary.com/floating-point-converter/ I can convert this when I tick single and raw hexadecimal value, then I receive 12345678, the value I should have (I know what is sent).
But now I need to do that conversion in PHP. I haven't any idea how this could be done. After some reading I figured out it is a Floating Point, but how to convert this like done on that website.
Is there someone that can help me with this!
Thanks a lot!
With the quite cryptic pack and unpack functions, it can be done in a one-liner:
function rawSingleHex($num) {
return strrev(unpack('h*', pack('f', $num))[1]);
}
This "packs" the number as its binary representation, then "unpacks" it in an array with one element: the binary representation in hexadecimal format. This format has the digits in the reversed order, so the function reverses that in the final result.
Call it by passing the floating point number:
echo rawSingleHex(5.6904566139035E-28);
Output:
12345678
Without pack/pack
(this was my original answer, but with the first option being available, this is not the advised way to proceed)
The binary format is explained in Wikipedia's article on the Single-precision floating-point format.
Here is a PHP function that implements the described procedure:
function rawSingleHex($num) {
if ($num == 0) return '00000000';
// set sign bit, and add another, higher one, which will be stripped later
$sign = $num < 0 ? 0x300 : 0x200;
$significant = abs($num);
$exponent = floor(log($significant, 2));
// get 24 most significant binary bits before the comma:
$significant = round($significant / pow(2, $exponent-23));
// exponent has exponent-bias format:
$exponent += 127;
// format: 1 sign bit + 8 exponent bits + 23 significant bits,
// without left-most "1" of significant
$bin = substr(decbin($sign + $exponent), 1) .
substr(decbin($significant), 1);
// assert that result has correct number of bits:
if (strlen($bin) !== 32) {
return "unexpected error";
}
// convert binary representation to hex, with exactly 8 digits
return str_pad(dechex(bindec($bin)), 8, "0", STR_PAD_LEFT);
}
It outputs the same as in the first solution.

PHP convert integer to 32 bit (4 Byte) hex for socket programming

I need to convert integer to a 4 byte (32 bit) hex for sending it as ACK to a device i am currently trying to integrate.
For example
3 = 00000003
15 = 0000000F
Check http://www.mathsisfun.com/binary-decimal-hexadecimal-converter.html
1. Select signed 32 bit from the dropdown
2. Enter the value in decomal text box
3. Check value in hex field.
I am using php pack function with this parameter but based on the response from the device, it does not seem to be the correct approach.
$reply = pack(L*,$num);
Is this the correct parameter or there is some other way.
Please suuggest.
i would do
$a = 15;
var_dump( sprintf("%08X", $a) );
$a = 3;
var_dump( sprintf("%08X", $a) );
this outputs
string(8) "0000000F"
string(8) "00000003
08X means make a 8 char string padded with 0 (if needed) with the argument being treated as hex. (Upper case letters)
so in your example
$reply = sprintf("%08X", $num)

Use numbers starting with 0 in a variable in php

Hi i need to save a 010 number in $number and if i do like this php will remove the starting 0
$number = 010
And echo of this will return 10 how can i make it not to remove the initial 0
BR
Martin
Use it as a String:
$number = '010';
Use str_pad() function.
echo str_pad('10',3,'0',STR_PAD_LEFT)
http://php.net/manual/en/function.str-pad.php
Do remember that numbers starting with 0 can also be treated as octal number notation by the PHP compiler, hence if you want to work with decimal numbers, simply use:
$num = '010';
This way the number is saved, can be stored in the database and manipulated like any other number. (Thx to the fact that PHP is very loosely typed language.)
Another method to use would be:
Save number as $num = 10;
Later while printing the value you can use sprintf, like:
sprintf("%03d", $i);
This will print your number in 3 digit format, hence 0 will be added automatically.
Another method:
<?php
$num = 10;
$zerofill = 3;
echo str_pad($num, $zerofill, "0", STR_PAD_LEFT);
/* Returns the wanted result of '010' */
?>
You can have a look at the various options available to you and make a decision. Each of the method given above will give you a correct output.

How do you use the raw_output return value of md5() in PHP?

I'm pretty inexperienced in PHP so this may be obvious to some of you, but if I call md5($mystring,true) in PHP it says it returns a "raw binary format with a length of 16". So what is that? Is it an array? An array of what? How do I read the individual bits and bytes of that return value?
None of the examples I can find online use it without going straight into base64_encode() or something. I just want to be able to check the fifth bit, or the third byte, for example.
var_dump(md5("string", TRUE));
"Raw binary format" means a string (as strings are binary-safe in PHP):
string(16) "�\����= �(��^{!"
If you want to read a byte out of that, use the $string[5] offset syntax for that. Or to extract a single bit out of the fifth byte for example:
$bit4_from_5th_byte = ord($result[5]) & (1 << 4);
It returns it as a "string" with each Character being a byte of the output. What you might consider instead is using the hex output of md5() without the second parameter and converting substrings of it to numbers using intval() with 16 as the base parameter. Like so:
$hash = md5($raw);
$byte = intval(substr($hash, 0, 2), 16);
An MD5 hash is a 128bit number, e.g. 16 bytes of raw binary data. For legibility, PHP's md5() function defaults to outputting this as a human readable string, where those 16 binary bytes get converted into a 32 character alpha-numeric string.
When you specify that second true parameter for MD5, you're telling PHP to return that raw 128bit number instead of the human readable version.
The RAW output of MD5 is the plain binary string of the hash. You cannot print it to the screen since it's not encoded as actual ASCII characters but binary numbers. This is only useful if you need to store or transfer the hash in a binary format.
To get the individual bits:
$md5 = md5( "b", true );
$l = strlen( $md5 );
$bits = "";
for( $i = 0; $i < $l; ++$i ) {
$num = ord( $md5[$i] );
for( $j = 7; $j >= 0; --$j ) {
$bits .= ( $num & ( 1 << $j ) ) ? "1" : "0";
}
}
echo $bits."\n";
//10010010111010110101111111111110111001101010111000101111111011000011101011010111000111000111011101110101001100010101011110001111
echo asciibin2hex( $bits ) == md5("b"); // true
So we go byte by byte, and since it is in string form, we need to convert it to ASCII number by ord(). Now go through the byte, bit by bit and see which are turned on and which are turned off and concatenate to the bit string. Go to next byte and rinse and repeat until all 128 bits are read.
Read third bit ( from the left ) in third byte:
ord( $md5[2] ) & ( 1 << ( 8 - 3 ) )
returns 1 if the bit is turned on, 0 otherwise

Categories