0

Operations on bits. How to take 2 bits from byte like this: take first 2 from 12345678 = 12; Make new byte = 00000012

For example as asked in discussion by jspit :

$char = 'z'; //is 122, 0111 1010
$b = $char & '?'; // ? is 63, 0011 1111
echo $b; //$b becomes 58 and shows ':'
//if integer used you get:
$b = $char & 63;// 63 is 0011 1111 as '?' but $char is string and you get 0 result:
echo $b; //$b becomes 0 because conversion to integer is used from string and $char becomes 0 and get 0 & 63 = 0, and here is error.

For clearance operation is on bits not on bytes, but bits from bytes. 'string' >> 1 not work, but this is second problem.

Codes of char You can check on my site generating safe readable tokens, with byte template option on. Site is in all available languages.

I think I found good answer here: how to bitwise shift a string in php?

PS. Sorry I cant vote yours fine answers but I have no points reputation here to do this ;)...

  • The terms “bits” and “bytes” are usually associated with binary. `12345678` is `101111000110000101001110` in binary, and the two bits, both most significant (ignoring leading zeros from unknown word size) and least significant are `10` which would be `2` in decimal. This doesn’t match what you are expecting. Do you mean first two “digits”? – Chris Haas Nov 30 '22 at 03:51
  • My question was not clear. I need operation on bits not on bytes of string. 123456789... means bits. For more clearence I should not notice 123356... but it should be 76543210. I need take, like I described: take 2 first bites - last in computer syntax, from byte of 8 bites make from this byte like I described above. – Daro from Poland Nov 30 '22 at 04:28
  • When you say `12345678`, you mean any 8-bit binary number, and `1` means the “left-most” or most-significant bit, `2` means the second from the left, `3` third from the left, and so, and these are always going to be either a 1 or a 0? So really you might have `01100011` and you want `00000001`, or `11000000` giving you `00000011`? Is that right? – Chris Haas Nov 30 '22 at 04:49
  • Yes, like this...thx ! – Daro from Poland Nov 30 '22 at 05:03
  • Why are you dealing with a string? – Chris Haas Nov 30 '22 at 05:04
  • I don't understand the text at all. Some reproducible examples (PHP code) with an input from which the data type emerges and the expected result also with data type (integer, string,?) would be helpful. – jspit Nov 30 '22 at 09:59
  • I need own base64_encode faster and not 64 but 62 without + and /sign, so template is: 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ – Daro from Poland Nov 30 '22 at 11:05
  • This [answer](https://stackoverflow.com/a/4848526/231316) has an arbitrary base/alphabet convertor, and this [example](https://3v4l.org/auNhm) has an implementation, will that work? Also, [this answer](https://stackoverflow.com/a/364626/231316) from over a decade ago strongly discourages this, which I agree with. – Chris Haas Nov 30 '22 at 12:42

2 Answers2

0

I hope you understand bits can only be 0 or 1, I'm assuming when you say "12345678" you're just using those decimal symbols to represent the positions of each bit. If that is the case, then you're looking for bitwise operators.

More specifically:

$new = $old >> 6;

This bitwise shift operation will shift all bits 6 positions to the right, discarding the 6 bits that were there before.

You can also use an or operation with a bitmask to ensure only 2 bits remain, in case the variable had more than 8 bits set:

$new = ($old >> 6) | 0b00000011;
Havenard
  • 27,022
  • 5
  • 36
  • 62
  • Yes something like that, thx for good tips... – Daro from Poland Nov 30 '22 at 05:00
  • Actually i want first from left bits to make byte and place this bits from right to left, and left variable, make it, from rest 6 bits. On finish We get two bytes. Thats is the plan :), and here I will use & operator on orginal initial byte to get secound variable like this: $b = $char & '?'; $char is string type and to get string We must use '?' not 63 byte 0011 1111, becouse of throwing $char to integer to 0, this is mentioned in Bitwise Operators in PHP manual: "If both operands for the &, | and ^ operators are strings, then the operation will be performed on the ASCII values ..." – Daro from Poland Nov 30 '22 at 05:15
  • You can grab the 6 rightmost bits with a bitmask, `$right = $bits & 0b00111111;`, and then the 2 leftmost bits with a shift operation, `$left = $bits >> 6;`. – Havenard Nov 30 '22 at 06:07
  • And that is the solution like I checked other answers. Second readable signs should be used. This operation is on strings therefore & should be used on the same type of string then instead 00111111; must be '?' used. >> shift can't be used on strings and there We must used ord and chr function. – Daro from Poland Nov 30 '22 at 10:37
0
function highestBitsOfByte(int $byte, int $count = 2):int {
   if($count < 0 OR $count > 8) return false;  //Error
   return ($byte & 0xFF) >> (8-$count); 
}

$input = 0b10011110;

$r = highestBitsOfByte($input,2);

echo sprintf('%08b',$r);

The integer number is limited to the lowest 8 bits with & 0xFF. Then the bits are shifted to the right according to the desired length.

example to try: https://3v4l.org/1lAvO

If there is a character as input and the fixed number of 2 bits is required, then this can be used:

$chr = 'z';  //0111 1010

$hBits = ord($chr) >> 6;

echo sprintf('%08b',$hBits);  //00000001
jspit
  • 7,276
  • 1
  • 9
  • 17
  • Character is used because PHP operating mainly, widely on strings as bytes. For example random_bytes() generates strings not integers, and random_bytes(1 ) >> 6 not work and always results with 0. – Daro from Poland Nov 30 '22 at 12:39
  • If you have characters, you have to work with ord(). See above in my answer. The result is an integer. If you want to make a character out of it again, you have to use chr(). – jspit Nov 30 '22 at 15:00