How to check an individual binary digit

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By LDTK

Suppose that the binary form of var a is:
var a = 0b11101101
How can I check and receive the state of a particular bit as output?
Example: Imagine there is a operation “state” that outputs the nth digit of the variable a:

state(n, a)

Then, something like:

func _ready():
   print(state(3, a))
------------------------------
OUTPUT: 1

Prints the 3rd digit of the number. (In this case, 1)

Sorry for the convoluted question

Out of curiosity, what’s your end goal here? If your goal is to check a list of bit flags for a particular flag, this can be achieved using bitwise operators like & (AND), | (OR) and ^ (XOR).

Calinou | 2021-02-20 18:08

:bust_in_silhouette: Reply From: matterda

I haven’t found a real solution to your problem.

I have tried the obvious, i.e., converting a to a string. However, String(a) returns “237” and not “0b11101101”. So it does not work.

A workaround could be, if it is possible in your project, to define a as a String (var a = 0b11101101) and then get the value at a particular position by just calling a[n].

:bust_in_silhouette: Reply From: deaton64

Hi,
Convert the number to binary, shove the bits in an array and return the bit

extends Node2D

var a = 0b11101101

func _ready() -> void:
	print(state(3, a))
	
func state(n, q):
	var bits = [0, 0, 0, 0, 0, 0, 0, 0]
	var bit = 7
	while q > 0:
		bits[bit] = (q % 2)
		q /= 2
		bit -= 1
	return(bits[7-n])
:bust_in_silhouette: Reply From: Calinou

It sounds like you’re trying to check for the presence of specific flags in a bitfield.

Try something like this instead, which is more readable:

extends Node2D

# The `<<` operators performs a bit shift to the left, which can be used to elevate a number to the power of the righthand side quickly (when used with `1` on the lefthand side).
const FLAG_FALLING = 1 << 0  # 1
const FLAG_FLAMMABLE = 1 << 1  # 2
const FLAG_SLIPPERY = 1 << 2  # 4
const FLAG_NONSOLID = 1 << 3  # 8


func _ready() -> void:
    # The bitwise `|` operator can be used to combine flags safely.
    # `+` can also be used, but it's less safe as it won't prevent you from adding the same flag multiple times (which is invalid).
    var block_flags = FLAG_FALLING | FLAG_SLIPPERY

    print("Falling: ", has_flag(block_flags, FLAG_FALLING))
    print("Flammable: ", has_flag(block_flags, FLAG_FLAMMABLE))
    print("Slippery: ", has_flag(block_flags, FLAG_SLIPPERY))
    print("Nonsolid: ", has_flag(block_flags, FLAG_NONSOLID))


func has_flag(bitfield, flag):
    # The bitwise `&` operator will return a number with all bits "in common" between the two numbers set to `1`, and all other bits set to `0`. If no flags match, the returned number will be `0` since there will be no bits in common between the two numbers.
    # Here, we convert it to a boolean since we are only interested in whether
    return bool(bitfield & flag)

This prints:

Falling: True
Flammable: False
Slippery: True
Nonsolid: False
1 Like
:bust_in_silhouette: Reply From: brainbug
func set_state(n:int,value:int)->int:
	value  |= (1 << n)
	return value

func get_state(n : int,value: int  )->int:
	var _state : bool = value & (1 << n) !=0
	return 1 if _state else 0  

func toggle_state(n:int ,value:int)->int:
	value ^= (1 << value)
	return value 

& is bitwise and
| is bitwise or
<< is left shift