>

I practiced converting between binary, decimal, and hexadecimal using bc, printf, and Python, the math that underpins subnetting, file permissions, and byte-level analysis. Fluency in base conversion makes CIDR masks and octal modes intuitive rather than memorized.

Objective & Context

Networking and permissions are base-2 and base-8 at heart. This lab builds quick conversion skills so subnet masks, chmod octals, and hex dumps read naturally, directly supporting the subnetting and permissions labs.

Learning Objectives

  • Convert between binary, octal, decimal, and hexadecimal with bc.
  • Format numbers in any base with printf.
  • Convert bases quickly in Python one-liners.
  • Read IPv4 octets as binary to understand subnet masks.
  • Translate chmod octal modes to binary permission triples.

Environment & Prerequisites

Prerequisites

  • Linux shell with bc, printf (shell builtin), and python3.
  • Sample values to convert: IP octets, permission bits, byte values.
  • No networking or root needed; this lab is pure computation.
  • Curiosity about why 255, 8, and 16 appear everywhere in computing.

Step-by-Step Execution

1. Decimal to binary with bc

echo "obase=2; 192" | bc

Expected output:

11000000

What this teaches: obase=2 switches bc's output base; 192 decimal is 11000000 binary. bc handles arbitrary precision, so it converts values far beyond 64-bit.

2. Decimal to hex with printf

printf '%X\n' 255

Expected output:

FF

What this teaches: printf %X formats as uppercase hex; %x gives lowercase and %o gives octal. Note that printf has no binary format specifier (%b expands backslash escapes inside a string argument, it does not print binary); for binary output use echo "obase=2; 255" | bc or Python's bin(255). printf is the fastest formatter for scripts because it is a shell builtin.

3. Hex to decimal in Python

python3 -c "print(int('FF',16))"

Expected output:

255

What this teaches: int('FF', 16) parses a base-16 string to decimal; the second argument sets the base (2, 8, 16), and bin()/hex() go the other way. Python is the pocket calculator for bases.

4. Decode a chmod octal to binary permission triples

echo "obase=2; 755" | bc

Expected output:

111101101

What this teaches: 755 in binary is 111 101 101, read as three permission triples: rwx, r-x, r-x. Each octal digit is exactly three bits, which is why octal is the natural base for Unix permissions; grouping the output in threes makes the mapping visual.

How It Works

Positional notation is one idea in many bases: each digit multiplies a power of the base. Binary (base 2) mirrors hardware bits, octal (base 8) groups bits in threes which maps perfectly onto Unix permission triples, decimal (base 10) is human convention, and hex (base 16) groups bits in fours, matching bytes as two digits. Converting is just re-expressing the same value.

Networking leans on binary because subnet masks are contiguous bit runs: 255.255.255.0 is 24 ones then 8 zeros, i.e. a /24. Permissions lean on octal because rwx is three bits, so 7 is full and 5 is read+execute. Hex dominates dumps and hashes because two hex digits are exactly one byte, keeping binary data compact and readable.

The tools each cover a niche: bc is the arbitrary-precision calculator for long conversions, printf formats numbers inside scripts without spawning Python, and Python one-liners handle parsing plus formatting in a single expression. Knowing all three means never reaching for a web converter.

Validation & Testing

Convert an IP octet (192) to binary and a permission value (755) reasoning, then verify round-trips back to decimal. Pass criteria: conversions agree across bc, printf, and Python and match manual calculation.

Troubleshooting

SymptomLikely causeFix
bc prints 0 for obase=16 conversionsibase was set after obase, and obase is interpreted in the new ibaseSet obase before ibase, or use obase=16 with ibase untouched
printf %x shows unexpected ffffffffThe value was treated as signed 32-bit negativeMask first: printf '%x' $(( value & 0xffffffff ))
Python int() raises ValueErrorThe string contains characters invalid for the baseStrip prefixes like 0x first, or pass base 0 to auto-detect
Binary string misaligns octetsLeading zeros were droppedPad with zfill(8) or printf %08d for fixed-width octets
bc -l changed integer results-l loads the math library and sets scale=20Use plain bc for integer base conversion; reserve -l for floating point
Confusion between 1K=1000 and 1KiB=1024Storage vendors use decimal, OS tools use binaryCheck units: ls -h uses powers of 1024, du --si uses 1000
Advanced: Troubleshooting
  • bc base confusion: set ibase before the value and obase for output; order matters.
  • Wrong hex case: use %x for lowercase, %X for uppercase in printf.
  • Leading zeros lost: pad with printf width specifiers when needed.

Key Results

  • Converted fluently across base-2, base-10, and base-16.
  • Applied binary math directly to subnet mask reasoning.
  • Verified conversions round-trip across 3 independent tools.
  • Made octal permission values intuitive rather than memorized.

Key Takeaways

  • Binary maps to bits (subnets), octal to permission triples, hex to bytes.
  • bc converts with obase/ibase; set obase first.
  • printf %x/%o formats inside scripts with zero overhead.
  • Python int(s, base) parses; bin()/hex() format back.
  • Pad binary octets to 8 digits when comparing masks.

Practice Challenges

Challenge 1: Mask in binary

Goal: print 255.255.240.0 as four 8-digit binary octets and state the CIDR prefix length.

Hint: convert each octet with printf or Python, then count the 1 bits.

Challenge 2: Permission decoder

Goal: write a one-liner that takes 750 and prints rwxr-x---.

Hint: map each octal digit to its 3-bit binary form, then 1 to r/w/x by position.