ABOUT BINARY, BITS AND BYTES

Share your advanced PureBasic knowledge/code with the community.
User avatar
Mijikai
Addict
Addict
Posts: 1520
Joined: Sun Sep 11, 2016 2:17 pm

ABOUT BINARY, BITS AND BYTES

Post by Mijikai »

Code (PB 6.04 LTS - x64):

Code: Select all

EnableExplicit

;ABOUT BINARY, BITS AND BYTES

;Computers work with binary numbers.
;Binary numbers are build up with Bits.
;A singular Bit can either have the value of one or zero.
;The computer understands this as current and no current.

;A Byte consists of 8 Bits or 2 Nibbles (4 Bits) and can represent 256 numbers.
;(4 * 4) * (4 * 4) = 256

;The binary representation of an Byte could look like this (8 Bits or 2 Nibbles):
;0110 1100

;The smalles binary number will look like this:
;0000 0000

;And the biggest like this:
;1111 1111

;128 would look like this:
;1000 0000
Debug "#Example 1 - The Bits of 128:"
Debug "10000000 = " + Str(%10000000)
Debug ""

;And 1 would be:
;0000 0001
Debug "#Example 2 - The Bits of 1:"
Debug "00000001 = " + Str(%00000001)
Debug ""

;The decimal value of every Bit in a Byte:
;128    64    32    16    8   4   2   1

;So what is the value of 0101 1010?
;      0                1              0              1              1             0             1             0     
;(0 * 128 = 0) + (1 * 64 = 64) + (0 * 32 = 0) + (1 * 16 = 16) + (1 * 8 = 8) + (0 * 4 = 0) + (1 * 2 = 2) + (0 * 1 = 0) = 90
Debug "#Example 3 - The value of a Byte:"
Debug RSet(Bin(90,#PB_Ascii),8,"0") + " = 90"
Debug ""

;Code Example:
Debug "#Example 4 - Code example:"

Procedure.i ByteValue(Binary.s)
  Protected index.i
  Protected count.i
  Protected value.i
  Binary = ReverseString(Binary)
  count = 1
  For index = 1 To 8
    value + Val(Mid(Binary,index,1)) * count
    count + (1 + index) % 1 + count;<- calculate 2, 4, 8, 16, 32, 64, 128
  Next
  ProcedureReturn value
EndProcedure

Debug "11001101 = " + Str(ByteValue("11001101"))
Debug "11001101 = " + Str(%11001101)
Debug "11111101 = " + Str(ByteValue("11111101"))
Debug "11111101 = " + Str(%11111101)
Debug ""

;Conversion table for a Nibble (Binary, Decimal, Hexadecimal):

;--------------------------
;|  BIN:  |  DEC: |  HEX: |
;--------------------------
;|  0000  |    0  |   0   |   
;|  0001  |    1  |   1   |  
;|  0010  |    2  |   2   |    
;|  0011  |    3  |   3   | 
;|  0100  |    4  |   4   |   
;|  0101  |    5  |   5   |   
;|  0110  |    6  |   6   |   
;|  0111  |    7  |   7   |    
;|  1000  |    8  |   8   |  
;|  1001  |    9  |   9   |  
;|  1010  |   10  |   A   |    
;|  1011  |   11  |   B   |   
;|  1100  |   12  |   C   |  
;|  1101  |   13  |   D   |   
;|  1110  |   14  |   E   |  
;|  1111  |   15  |   F   | 
;--------------------------

;The decimal value for every Hexadecimal in a Word (2 Bytes):
;4096   256   16    1

;So what is the value of 029A?
;       0                2                 9               A
;(0 * 4096 = 0) + (2 * 256 = 512) + (9 * 16 = 144) + (10 * 1 = 10) = 666

;Ways for a programmer to interact with Bits:

;For example Bit shifting moves the Bits to the left or right (Bit shifting operators << and >>):
Debug "#Example 5 - Bit shifting:"
Debug "00010000 << 1 = " + ReplaceString(RSet(Bin(%00010000 << 1,#PB_Ascii),8,"0"),"10","1<-0") + " SHIFT LEFT"
Debug "00010000 >> 1 = " + ReplaceString(RSet(Bin(%00010000 >> 1,#PB_Ascii),8,"0"),"01","0->1") + " SHIFT RIGHT"
Debug ""

;What is it good for?
;It can be used to determine the state of a single Bit or for very fast multiplications and divisions.
Debug "#Example 6 - Fast multiplication and division:"
Debug "1 << 1 = " + Str(1 << 1)
Debug "1 << 2 = " + Str(1 << 2)
Debug "2 >> 1 = " + Str(2 >> 1)
Debug "4 >> 1 = " + Str(4 >> 1)
Debug ""

;More operators from the manual:

;Bitwise OR (|): 
;The result of this operator will be the value of the expression on the LHS or'ed with the value of the expression on the RHS, bit for bit.
;The value of each bit is set according to the table below. Additionally, 
;if the result of the operator is not used and there is a variable on the LHS, 
;then the result will be stored directly in that variable. This operator cannot be used with strings.

; LHS | RHS | Result
; ------------------
;  0  |  0  |    0
;  0  |  1  |    1
;  1  |  0  |    1
;  1  |  1  |    1

; Bitwise AND (&):
;The result of this operator will be the value of the expression on the LHS anded with the value of the expression on the RHS, bit for bit.
;The value of each bit is set according to the table below. Additionally, if the result of the operator is not used and there is a variable on the LHS,
;then the result will be stored directly in that variable. This operator cannot be used with strings.

; LHS | RHS | Result
; ------------------
;  0  |  0  |    0
;  0  |  1  |    0
;  1  |  0  |    0
;  1  |  1  |    1

; Bitwise XOR (!):
;The result of this operator will be the value of the expression on the LHS xor'ed with the value of the expression on the RHS, bit for bit.
;The value of each bit is set according to the table below. Additionally, if the result of the operator is not used and there is a variable on the LHS,
;then the result will be stored directly in that variable. This operator cannot be used with strings.

; LHS | RHS | Result
; ------------------
;  0  |  0  |    0
;  0  |  1  |    1
;  1  |  0  |    1
;  1  |  1  |    0

; Bitwise NOT (~):
;The result of this operator will be the not'ed value of the expression on the RHS, bit for bit.
;The value of each bit is set according to the table below. This operator cannot be used with strings.
 
; RHS | Result
; ----------
;  0  |    1
;  1  |    0
 

;Useful macros for Bits:

Macro BitGet(_var_,_bit_)
  ((_var_) >> (_bit_)) & 1
EndMacro

Macro BitSet(_var_,_bit_)
  _var_ | (1 << (_bit_))
EndMacro

Macro BitReset(_var_,_bit_)
  _var_ & ~ (1 << (_bit_))
EndMacro

Procedure.i BitMacros()
  Protected int.i
  int = %100010110000111100001101
  Debug "BitGet(" + Bin(int) + ",X)"
  Debug "Bit POS 0  = " + Str(BitGet(int,0)) + " 10001011000011110000110(1)"
  Debug "Bit POS 19 = " + Str(BitGet(int,19)) + " 1000(1)0110000111100001101"
  Debug "Bit POS 22 = " + Str(BitGet(int,22)) +  " 1(0)0010110000111100001101"
  Debug "BitSet(" + Bin(int) + ",X)"
  BitSet(int,22)
  Debug "Bit SET 22 = " + Str(BitGet(int,22))
  Debug "BitReset(" + Bin(int) + ",X)"
  BitReset(int,22)
  Debug "Bit RESET 22 = " + Str(BitGet(int,22))
  ProcedureReturn #Null
EndProcedure

Debug "#Example 6 - Bit Macros:"
BitMacros()
Debug ""
User avatar
STARGÅTE
Addict
Addict
Posts: 2232
Joined: Thu Jan 10, 2008 1:30 pm
Location: Germany, Glienicke
Contact:

Re: ABOUT BINARY, BITS AND BYTES

Post by STARGÅTE »

Your ByteValue() function is already implemented in Pure Basic: Val().

Code: Select all

Debug Val("%11001101")
Debug Bin(205)
Regarding your bit macros, they are not "safe". One additional bracket is needed around the calculation and around _val_, otherwise you have problems with operator priority:

Code: Select all

Debug BitGet(%101, 0) | BitGet(%101, 2)<<2 ; gives 0, but should be 5
Debug Bin(BitReset(2+4, 1)) ; gives 110 but should be 100
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Lizard - Script language for symbolic calculations and moreTypeface - Sprite-based font include/module
User avatar
Mijikai
Addict
Addict
Posts: 1520
Joined: Sun Sep 11, 2016 2:17 pm

Re: ABOUT BINARY, BITS AND BYTES

Post by Mijikai »

Thank you for the tips STARGÅTE.

I can change the BitGet() macro:

Code: Select all

Macro BitGet(_var_,_bit_)
  (((_var_) >> (_bit_)) & 1)
EndMacro
However the two others wont work, how should i do it?

Code: Select all

EnableExplicit

Macro BitSet(_var_,_bit_)
  ((_var_) | (1 << (_bit_)))
EndMacro

Macro BitReset(_var_,_bit_)
  ((_var_) & ~ (1 << (_bit_)))
EndMacro

Procedure.i BitMacros()
  Protected int.i
  int = %100010110000111100001101
  BitSet(int,22)
  BitReset(int,22)
  ProcedureReturn #Null
EndProcedure
User avatar
idle
Always Here
Always Here
Posts: 5899
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: ABOUT BINARY, BITS AND BYTES

Post by idle »

if you don't mind fasm backend

Code: Select all

CompilerIf SizeOf(Integer) = 8
  Macro ecx : rcx : EndMacro 
  Macro eax : rax : EndMacro
CompilerEndIf   

Macro BitSet(bitfield,bit) 
  EnableASM
  bts bitfield , bit 
  DisableASM 
EndMacro 

Macro BitReset(bitfield,bit)
  EnableASM 
  btr bitfield,bit
  DisableASM 
EndMacro   

Macro BitToggle(bitfield,bit)
  EnableASM 
  btc bitfield,bit
  DisableASM 
EndMacro   

Macro BitGet(bitfield,bit)
  (((bitfield) >> (bit)) & 1)
EndMacro   

Global mybit.l 

BitSet(mybit,16) 
If BitGet(mybit,16)    
  Debug "on: " + Bin(mybit,#PB_Long) 
EndIf   

BitReset(mybit,16) 
If Not BitGet(mybit,16)    
  Debug "off: " + Bin(mybit,#PB_Long)  
EndIf   

BitToggle(mybit,16) 
Debug "toggle on: " + Bin(mybit,#PB_Long)  
BitToggle(mybit,16) 
Debug "toggle off: " + Bin(mybit,#PB_Long) 

Post Reply