Bitwise Operators: Difference between revisions

From QB64 Phoenix Edition Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
 
(5 intermediate revisions by the same user not shown)
Line 6: Line 6:
* '''EQV''': True if both inputs are the same
* '''EQV''': True if both inputs are the same
* '''IMP''': True unless first input is true and second is false
* '''IMP''': True unless first input is true and second is false


{{PageSyntax}}
{{PageSyntax}}
Line 13: Line 14:
: ''result'' = '''NOT''' ''value1''
: ''result'' = '''NOT''' ''value1''
If ''value1'' or ''value2'' are non-integer numeric types, they are rounded to the nearest integer.
If ''value1'' or ''value2'' are non-integer numeric types, they are rounded to the nearest integer.


{{PageDescription}}
{{PageDescription}}
Line 19: Line 21:
Again, note that the NOT operator only has one operand. It is shown in the same table for convenience.
Again, note that the NOT operator only has one operand. It is shown in the same table for convenience.


If one input has more bits than the other (say, an INTEGER vs a LONG) the shorter will be considered to have 0's in the missing bit positions if it is positive, or 1's if it is negative. This scheme comes about because of the [[wikipedia:Two's complement|Two's Complement]] system for representing negative numbers. As a general rule, there should not be any surprises.
If one input has more bits than the other (say, an INTEGER vs a LONG) the shorter will be considered to have 0's in the missing bit positions if it is positive, or 1's if it is negative. This scheme comes about because of the [[Wikipedia:Two's complement|Two's Complement]] system for representing negative numbers. As a general rule, there should not be any surprises.


=== Use as logical operators ===
=== Use as logical operators ===
QB64 does not have AND/OR/NOT operators dedicated to operating on the overall truth of values. A numeric value is defined to be ''false'' if it is equal to 0, and ''true'' for any other value, though -1 is the standard ''true'' value,  returned by the <, <= etc. operators. One can use the bitwise operators mostly like regular logical operators, but with caution. For instance, 3 is a true value, so as a logical operator NOT 3 would be 0 (false). Because it is in fact a bitwise operator, it evaluates to -4.
QB64 does not have AND/OR/NOT operators dedicated to operating on the overall truth of values. A numeric value is defined to be ''false'' if it is equal to 0, and ''true'' for any other value, though -1 is the standard ''true'' value,  returned by the <, <= etc. operators. One can use the bitwise operators mostly like regular logical operators, but with caution. For instance, 3 is a true value, so as a logical operator NOT 3 would be 0 (false). Because it is in fact a bitwise operator, it evaluates to -4.


{{PageExamples}}
{{PageExamples}}
;Example 1:Use '''AND''' to mask certain bits in a value. In this example, the 1's in the mask (y&) specify which bits in (x&) we are interested in, forcing all others to 0.
;Example 1:Use '''AND''' to mask certain bits in a value. In this example, the 1's in the mask (y&) specify which bits in (x&) we are interested in, forcing all others to 0.
{{CodeStart}}
{{CodeStart}}
x& = VAL("&B101010") 'Arbitrary collection of bits
x& = {{Cl|VAL}}({{Text|<nowiki>"&B101010"</nowiki>|#FFB100}}) {{Text|<nowiki>'Arbitrary collection of bits</nowiki>|#919191}}
y& = VAL("&B001100") 'A bit mask
y& = {{Cl|VAL}}({{Text|<nowiki>"&B001100"</nowiki>|#FFB100}}) {{Text|<nowiki>'A bit mask</nowiki>|#919191}}
PRINT "Input 1: "; BIN$(x&, 6) '6 indicates we want 6 bits of output
{{Cl|PRINT}} {{Text|<nowiki>"Input 1: "</nowiki>|#FFB100}}; {{Text|BinStr$|#55FF55}}(x&, {{Text|6|#F580B1}}) {{Text|<nowiki>'6 indicates we want 6 bits of output</nowiki>|#919191}}
PRINT "Input 2: "; BIN$(y&, 6)
{{Cl|PRINT}} {{Text|<nowiki>"Input 2: "</nowiki>|#FFB100}}; {{Text|BinStr$|#55FF55}}(y&, {{Text|6|#F580B1}})
PRINT "Output:  "; BIN$(x& AND y&, 6)
{{Cl|PRINT}} {{Text|<nowiki>"Output:  "</nowiki>|#FFB100}}; {{Text|BinStr$|#55FF55}}(x& {{Cl|AND}} y&, {{Text|6|#F580B1}})


'Converts the number n& to a string of binary digits, digits& long (padding or truncating as necessary).
{{Text|<nowiki>'Converts the number n& to a string of binary digits, digits& long (padding or truncating as necessary).</nowiki>|#919191}}
FUNCTION BIN$ (n&, digits&)
{{Cl|FUNCTION}} {{Text|BinStr$|#55FF55}} (n&, digits&)
     FOR i& = digits& - 1 TO 0 STEP -1
     {{Cl|FOR}} i& = digits& - {{Text|1|#F580B1}} {{Cl|TO}} {{Text|0|#F580B1}} {{Cl|STEP}} {{Text|-1|#F580B1}}
         IF (n& AND 2 ^ i&) THEN B$ = B$ + "1" ELSE B$ = B$ + "0"
         {{Cl|IF}} (n& {{Cl|AND (boolean)|AND}} {{Text|2|#F580B1}} ^ i&) {{Cl|THEN}} B$ = B$ + {{Text|<nowiki>"1"</nowiki>|#FFB100}} {{Cl|ELSE}} B$ = B$ + {{Text|<nowiki>"0"</nowiki>|#FFB100}}
     NEXT
     {{Cl|NEXT}}
     BIN$ = B$
     {{Text|BinStr$|#55FF55}} = B$
END FUNCTION
{{Cl|END FUNCTION}}
{{CodeEnd}}
{{CodeEnd}}
{{OutputStart}}
{{OutputStart}}
Line 49: Line 52:
;Example 2:Use '''OR''' to combine bit flags into a single value. The presence of a flag can then be tested by using the flag as a mask with '''AND'''.
;Example 2:Use '''OR''' to combine bit flags into a single value. The presence of a flag can then be tested by using the flag as a mask with '''AND'''.
{{CodeStart}}
{{CodeStart}}
'The trick here is to give each flag a value corresponding to a different bit being 1
{{Text|<nowiki>'The trick here is to give each flag a value corresponding to a different bit being 1</nowiki>|#919191}}
FLAG_A& = VAL("&B0001")
FLAG_A& = {{Cl|VAL}}({{Text|<nowiki>"&B0001"</nowiki>|#FFB100}})
FLAG_B& = VAL("&B0010")
FLAG_B& = {{Cl|VAL}}({{Text|<nowiki>"&B0010"</nowiki>|#FFB100}})
FLAG_C& = VAL("&B0100")
FLAG_C& = {{Cl|VAL}}({{Text|<nowiki>"&B0100"</nowiki>|#FFB100}})
FLAG_D& = VAL("&B1000")
FLAG_D& = {{Cl|VAL}}({{Text|<nowiki>"&B1000"</nowiki>|#FFB100}})


flags& = FLAG_A& OR FLAG_C& 'Set flags A, C
flags& = FLAG_A& {{Cl|OR}} FLAG_C& {{Text|<nowiki>'Set flags A, C</nowiki>|#919191}}


'Use each flag as a bitmask to test for its presence:
{{Text|<nowiki>'Use each flag as a bitmask to test for its presence:</nowiki>|#919191}}
IF flags& AND FLAG_A& THEN PRINT "Flag A is set"
{{Cl|IF}} flags& {{Cl|AND (boolean)|AND}} FLAG_A& {{Cl|THEN}} {{Cl|PRINT}} {{Text|<nowiki>"Flag A is set"</nowiki>|#FFB100}}
IF flags& AND FLAG_B& THEN PRINT "Flag B is set"
{{Cl|IF}} flags& {{Cl|AND (boolean)|AND}} FLAG_B& {{Cl|THEN}} {{Cl|PRINT}} {{Text|<nowiki>"Flag B is set"</nowiki>|#FFB100}}
IF flags& AND FLAG_C& THEN PRINT "Flag C is set"
{{Cl|IF}} flags& {{Cl|AND (boolean)|AND}} FLAG_C& {{Cl|THEN}} {{Cl|PRINT}} {{Text|<nowiki>"Flag C is set"</nowiki>|#FFB100}}
IF flags& AND FLAG_D& THEN PRINT "Flag D is set"
{{Cl|IF}} flags& {{Cl|AND (boolean)|AND}} FLAG_D& {{Cl|THEN}} {{Cl|PRINT}} {{Text|<nowiki>"Flag D is set"</nowiki>|#FFB100}}
{{CodeEnd}}
{{CodeEnd}}
{{OutputStart}}
{{OutputStart}}
Line 70: Line 73:
;Example 3:Use '''XOR''' to toggle a bit flag (that is, change its state to the opposite of what it was). This example is the same as the '''OR''' example above, but with one extra line added. This time we enable flags A & C, then toggle flags A & B. This will disable flag A and enable B.
;Example 3:Use '''XOR''' to toggle a bit flag (that is, change its state to the opposite of what it was). This example is the same as the '''OR''' example above, but with one extra line added. This time we enable flags A & C, then toggle flags A & B. This will disable flag A and enable B.
{{CodeStart}}
{{CodeStart}}
'The trick here is to give each flag a value corresponding to a different bit being 1
{{Text|<nowiki>'The trick here is to give each flag a value corresponding to a different bit being 1</nowiki>|#919191}}
FLAG_A& = VAL("&B0001")
FLAG_A& = {{Cl|VAL}}({{Text|<nowiki>"&B0001"</nowiki>|#FFB100}})
FLAG_B& = VAL("&B0010")
FLAG_B& = {{Cl|VAL}}({{Text|<nowiki>"&B0010"</nowiki>|#FFB100}})
FLAG_C& = VAL("&B0100")
FLAG_C& = {{Cl|VAL}}({{Text|<nowiki>"&B0100"</nowiki>|#FFB100}})
FLAG_D& = VAL("&B1000")
FLAG_D& = {{Cl|VAL}}({{Text|<nowiki>"&B1000"</nowiki>|#FFB100}})


flags& = FLAG_A& OR FLAG_C& 'Set flags A, C
flags& = FLAG_A& {{Cl|OR}} FLAG_C& {{Text|<nowiki>'Set flags A, C</nowiki>|#919191}}
flags& = flags& XOR FLAG_A& XOR FLAG_B& 'Toggle flags A, B
flags& = flags& {{Cl|XOR}} FLAG_A& {{Cl|XOR}} FLAG_B& {{Text|<nowiki>'Toggle flags A, B</nowiki>|#919191}}


'Use each flag as a bitmask to test for its presence:
{{Text|<nowiki>'Use each flag as a bitmask to test for its presence:</nowiki>|#919191}}
IF flags& AND FLAG_A& THEN PRINT "Flag A is set"
{{Cl|IF}} flags& {{Cl|AND (boolean)|AND}} FLAG_A& {{Cl|THEN}} {{Cl|PRINT}} {{Text|<nowiki>"Flag A is set"</nowiki>|#FFB100}}
IF flags& AND FLAG_B& THEN PRINT "Flag B is set"
{{Cl|IF}} flags& {{Cl|AND (boolean)|AND}} FLAG_B& {{Cl|THEN}} {{Cl|PRINT}} {{Text|<nowiki>"Flag B is set"</nowiki>|#FFB100}}
IF flags& AND FLAG_C& THEN PRINT "Flag C is set"
{{Cl|IF}} flags& {{Cl|AND (boolean)|AND}} FLAG_C& {{Cl|THEN}} {{Cl|PRINT}} {{Text|<nowiki>"Flag C is set"</nowiki>|#FFB100}}
IF flags& AND FLAG_D& THEN PRINT "Flag D is set"
{{Cl|IF}} flags& {{Cl|AND (boolean)|AND}} FLAG_D& {{Cl|THEN}} {{Cl|PRINT}} {{Text|<nowiki>"Flag D is set"</nowiki>|#FFB100}}
{{CodeEnd}}
{{CodeEnd}}
{{OutputStart}}
{{OutputStart}}
Line 90: Line 93:
{{OutputEnd}}
{{OutputEnd}}


{{PageNavigation}}
 
{{PageReferences}}

Latest revision as of 12:26, 19 November 2024

Bitwise operators are much like the regular mathematics operators (+, * etc.) but are defined in terms of the individual bits of their operands. The full list of bitwise operators, with a brief summary of its operation:

  • NOT: Invert all bits
  • AND: True if both inputs are true
  • OR: True if one or both inputs are true
  • XOR: True if exactly one input is true
  • EQV: True if both inputs are the same
  • IMP: True unless first input is true and second is false


Syntax

With the exception of NOT, all the bitwise operators take two operands:

result = value1 AND value2

NOT goes before the value it operates on:

result = NOT value1

If value1 or value2 are non-integer numeric types, they are rounded to the nearest integer.


Description

Bitwise operators work by comparing the corresponding bits in each of the input values to generate a single bit in the output value. The operators differ in how they do the comparison. The table below shows the output bit for each pair of input bits:

               Table 4: The logical operations and its results.

       In this table, A and B are the Expressions to invert or combine.
              Both may be results of former Boolean evaluations.
  ┌────────────────────────────────────────────────────────────────────────┐
  │                           Logical Operations                           │
  ├───────┬───────┬───────┬─────────┬────────┬─────────┬─────────┬─────────┤
  │   ABNOT BA AND BA OR BA XOR BA EQV BA IMP B │
  ├───────┼───────┼───────┼─────────┼────────┼─────────┼─────────┼─────────┤
  │ truetrue  │ false │  true   │ true   │  false  │  true   │  true   │
  ├───────┼───────┼───────┼─────────┼────────┼─────────┼─────────┼─────────┤
  │ truefalse │ true  │  false  │ true   │  true   │  false  │  false  │
  ├───────┼───────┼───────┼─────────┼────────┼─────────┼─────────┼─────────┤
  │ falsetrue  │ false │  false  │ true   │  true   │  false  │  true   │
  ├───────┼───────┼───────┼─────────┼────────┼─────────┼─────────┼─────────┤
  │ falsefalse │ true  │  false  │ false  │  false  │  true   │  true   │
  └───────┴───────┴───────┴─────────┴────────┴─────────┴─────────┴─────────┘
   Note: In most BASIC languages incl. QB64 these are bitwise operations,
         hence the logic is performed for each corresponding bit in both
         operators, where true or false indicates whether a bit is set or
         not set. The outcome of each bit is then placed into the respective
         position to build the bit pattern of the final result value.

   As all Relational Operations return negative one (-1, all bits set) for
    true and zero (0, no bits set) for false, this allows us to use these
    bitwise logical operations to invert or combine any relational checks,
    as the outcome is the same for each bit and so always results into a
            true (-1) or false (0) again for further evaluations.

Again, note that the NOT operator only has one operand. It is shown in the same table for convenience.

If one input has more bits than the other (say, an INTEGER vs a LONG) the shorter will be considered to have 0's in the missing bit positions if it is positive, or 1's if it is negative. This scheme comes about because of the Two's Complement system for representing negative numbers. As a general rule, there should not be any surprises.

Use as logical operators

QB64 does not have AND/OR/NOT operators dedicated to operating on the overall truth of values. A numeric value is defined to be false if it is equal to 0, and true for any other value, though -1 is the standard true value, returned by the <, <= etc. operators. One can use the bitwise operators mostly like regular logical operators, but with caution. For instance, 3 is a true value, so as a logical operator NOT 3 would be 0 (false). Because it is in fact a bitwise operator, it evaluates to -4.


Examples

Example 1
Use AND to mask certain bits in a value. In this example, the 1's in the mask (y&) specify which bits in (x&) we are interested in, forcing all others to 0.
x& = VAL("&B101010") 'Arbitrary collection of bits
y& = VAL("&B001100") 'A bit mask
PRINT "Input 1: "; BinStr$(x&, 6) '6 indicates we want 6 bits of output
PRINT "Input 2: "; BinStr$(y&, 6)
PRINT "Output:  "; BinStr$(x& AND y&, 6)

'Converts the number n& to a string of binary digits, digits& long (padding or truncating as necessary).
FUNCTION BinStr$ (n&, digits&)
    FOR i& = digits& - 1 TO 0 STEP -1
        IF (n& AND 2 ^ i&) THEN B$ = B$ + "1" ELSE B$ = B$ + "0"
    NEXT
    BinStr$ = B$
END FUNCTION
Input 1: 101010
Input 2: 001100
Output:  001000
Example 2
Use OR to combine bit flags into a single value. The presence of a flag can then be tested by using the flag as a mask with AND.
'The trick here is to give each flag a value corresponding to a different bit being 1
FLAG_A& = VAL("&B0001")
FLAG_B& = VAL("&B0010")
FLAG_C& = VAL("&B0100")
FLAG_D& = VAL("&B1000")

flags& = FLAG_A& OR FLAG_C& 'Set flags A, C

'Use each flag as a bitmask to test for its presence:
IF flags& AND FLAG_A& THEN PRINT "Flag A is set"
IF flags& AND FLAG_B& THEN PRINT "Flag B is set"
IF flags& AND FLAG_C& THEN PRINT "Flag C is set"
IF flags& AND FLAG_D& THEN PRINT "Flag D is set"
Flag A is set
Flag C is set
Example 3
Use XOR to toggle a bit flag (that is, change its state to the opposite of what it was). This example is the same as the OR example above, but with one extra line added. This time we enable flags A & C, then toggle flags A & B. This will disable flag A and enable B.
'The trick here is to give each flag a value corresponding to a different bit being 1
FLAG_A& = VAL("&B0001")
FLAG_B& = VAL("&B0010")
FLAG_C& = VAL("&B0100")
FLAG_D& = VAL("&B1000")

flags& = FLAG_A& OR FLAG_C& 'Set flags A, C
flags& = flags& XOR FLAG_A& XOR FLAG_B& 'Toggle flags A, B

'Use each flag as a bitmask to test for its presence:
IF flags& AND FLAG_A& THEN PRINT "Flag A is set"
IF flags& AND FLAG_B& THEN PRINT "Flag B is set"
IF flags& AND FLAG_C& THEN PRINT "Flag C is set"
IF flags& AND FLAG_D& THEN PRINT "Flag D is set"
Flag B is set
Flag C is set


QB64 Programming References

Wiki Pages
Main Page with Articles and Tutorials
QB64 specific keywords (alphabetical)
Original QBasic keywords (alphabetical)
QB64 OpenGL keywords (alphabetical)
Keywords by Usage
Got a question about something?
Frequently Asked Questions about QB64
QB64 Phoenix Edition Community Forum
Links to other QBasic Sites:
Pete's QBasic Forum
Pete's QBasic Downloads