Hex Math, All Bases Covered

Arithmetic and bitwise operations on hex values with live output in hex, decimal, octal, and binary.

Instant ResultsLive Multi-BaseBitwise OpsMobile-First
Hex Calculator
0x
+
0x
Arithmetic
Bitwise
Result

Enter hex values above to calculate

Code reference: bitwise and base conversion across languages

The calculator above performs hex arithmetic and bitwise operations with simultaneous output in hexadecimal, decimal, octal, and binary. The reference below covers the same operations as written in production source code, so the value you computed in the browser can be carried straight into the language you actually ship in.

Number literal syntax by language

LanguageHexOctalBinary
C, C++0xFF0377 (bare leading zero)0b11111111 (GCC ext, C++14+)
Rust0xFF0o3770b11111111
Go0xFF0o377 or 03770b11111111
Java0xFF03770b11111111
Kotlin0xFFnot supported0b11111111
C#0xFFnot supported0b11111111
Swift0xFF0o3770b11111111
Python 30xFF0o3770b11111111
Ruby0xFF0o377 or 03770b11111111
PHP 8.1+0xFF0377 or 0o3770b11111111
Perl0xFF03770b11111111
JavaScript0xFF0o3770b11111111
TypeScript0xFF0o3770b11111111
Bash arithmetic$((0xFF))$((0377))$((2#11111111))
PowerShell0xFFnot direct0b11111111 (PS 7+)
PostgreSQLx'FF'::intn/ab'11111111'::int
MySQL0xFFn/ab'11111111'
Lua 5.3+0xFFn/an/a

Underscores as digit separators (0xFF_FF_FF_FF) are accepted in Rust, Go, Java 7+, C# 7+, Swift, Kotlin, Python 3.6+, and Ruby. C and C++ require single quotes instead (0xFF'FF'FF'FF). PHP and JavaScript use the same single-underscore form in 7.4+ and ES2021.

Bitwise operations and multi-base output

Systems languages: C, C++, Rust, Go

LanguageApply XORPrint as hex, decimal, octal
Cuint32_t c = a ^ b;printf("0x%X %u 0%o\n", c, c, c);
C++ (std::format)auto c = a ^ b;std::format("0x{:X} {} 0o{:o}", c, c, c)
Rustlet c: u32 = a ^ b;format!("0x{:X} {} 0o{:o}", c, c, c)
Goc := a ^ bfmt.Sprintf("0x%X %d 0o%o", c, c, c)

The full operator set is identical across these four: &, |, ^, ~, <<, >>. Signedness matters for right shift. An unsigned right shift fills with zero, a signed right shift on a negative value fills with one. C, C++, and Go pick behavior based on the variable’s type. Rust requires an explicit unsigned or signed type at the binding site.

JVM and .NET: Java, Kotlin, C#, Swift

LanguageApply XORLogical (zero-fill) right shift
Javaint c = a ^ b;int c = a >>> n;
Kotlinval c = a xor bval c = a ushr n
C#int c = a ^ b;int c = (int)((uint)a >> n);
Swiftlet c = a ^ blet c = Int(UInt32(bitPattern: a) >> n)

Java is the outlier with its dedicated >>> triple-arrow for logical right shift. Kotlin spells operators as keywords: and, or, xor, inv, shl, shr, ushr. C# and Swift route through the unsigned type to force zero-fill. C# 11 added >>> matching Java syntax.

JavaScript and TypeScript

OperationNumber (32-bit truncated)BigInt (arbitrary precision)
ANDa & ba & b (both operands BigInt)
ORa | ba | b
XORa ^ ba ^ b
NOT~a (returns int32)~a (infinite-width two’s complement)
Left shifta << na << BigInt(n)
Signed right shifta >> na >> BigInt(n)
Zero-fill right shifta >>> nnot available on BigInt
const a = 0xFFFFFFFFn;
const b = 0x0F0Fn;
const c = a ^ b;
console.log(c.toString(16).toUpperCase()); // "FFFFF0F0"
console.log(c.toString(10));                // "4294967280"
console.log(c.toString(8));                 // "37777770360"
console.log(c.toString(2));                 // "11111111111111111111000011110000"

The n suffix marks BigInt literals. Mixing BigInt and Number in the same expression throws a TypeError. Convert one side first with BigInt(x) or Number(x).

Scripting: Python, Ruby, PHP, Perl

LanguageApply XORFormat result in four bases
Pythonc = a ^ bf"{c:#x} {c} {c:#o} {c:#b}"
Rubyc = a ^ b"%#x %d %#o %#b" % [c, c, c, c]
PHP$c = $a ^ $b;sprintf("%X %d %o %b", $c, $c, $c, $c)
Perl$c = $a ^ $b;sprintf("%X %d %o %b", $c, $c, $c, $c)

Python and Ruby integers grow without bound, so NOT on a positive value returns a negative because the result is interpreted as infinitely-wide two’s complement. To recover the 32-bit unsigned view: (~x) & 0xFFFFFFFF. The same mask applies to Perl’s ~ operator on platforms where the integer width is configurable at build time.

Shells: Bash, Zsh, PowerShell

ShellApply XORConvert hex string to decimal
Bashc=$(( a ^ b ))echo $((16#FF)) or printf "%d\n" 0xFF
Zsh(( c = a ^ b ))printf "%d\n" 0xFF
PowerShell$c = $a -bxor $b[Convert]::ToInt32("FF", 16)

Bash arithmetic context ($(( ))) covers &, |, ^, ~, <<, >>. PowerShell spells the same operators out as -band, -bor, -bxor, -bnot, -shl, -shr. Both default to 64-bit signed math, so a value above 0x7FFFFFFFFFFFFFFF overflows silently in Bash and wraps to a negative in PowerShell.

Databases: PostgreSQL, MySQL, SQLite

DatabaseApply XOROutput as hex string
PostgreSQLSELECT a # b; (note: # is XOR)SELECT to_hex(c);
MySQLSELECT a ^ b;SELECT HEX(c);
SQLiteSELECT a ^ b;SELECT printf('%X', c);

PostgreSQL is the outlier. Its XOR operator is #, and ^ is exponentiation. MySQL and SQLite follow C convention. None of the three has a built-in binary-string formatter, so binary output usually requires a recursive CTE that divides the value by two and concatenates the remainder.

Common hex constants and bit patterns

HexDecimalBinaryTypical use
0x01100000001Bit 0 enable flag
0x0F1500001111Low nibble mask
0xF024011110000High nibble mask
0xFF25511111111Single-byte mask, u8 max
0x8012810000000Sign bit of a byte
0xFFFF65,53516 onesu16 max, 16-bit address mask
0xFFFFFFFF4,294,967,29532 onesu32 max, all-bits-set
0x7FFFFFFF2,147,483,6470 + 31 onesi32 max (INT_MAX)
0x800000002,147,483,6481 + 31 zerosi32 sign bit (INT_MIN as unsigned view)
0xCAFEBABE3,405,691,582mixedJava .class file magic number
0xDEADBEEF3,735,928,559mixedCommon uninitialized-memory poison
0xFEEDFACE4,277,009,102mixedMach-O magic number
0xBAADF00D3,131,961,357mixedLocalAlloc uninitialized marker on Windows

The poison patterns (0xDEADBEEF, 0xBAADF00D, 0xFEEDFACE) appear in uninitialized memory or unmapped regions on many platforms. They are chosen to be visibly wrong in a debugger and pronounceable when read aloud during a pairing session.

Width and signedness: NOT and shift across languages

LanguageNOT widthRight shift on a negative value
C, C++type-dependent (uint8_t → 8 bits, int → typically 32)implementation-defined; in practice arithmetic
Rusttype-dependent and explicit at bindingarithmetic on signed, logical on unsigned
Gotype-dependent and explicit at bindingarithmetic on signed, logical on unsigned
Javaalways 32 (int) or 64 (long)arithmetic with >>, logical with >>>
C#32 or 64 by defaultarithmetic with >>, logical via cast or >>> (C# 11+)
Swifttype-dependentarithmetic on signed, logical on unsigned
Pythoninfinite (NOT returns a negative)arithmetic
Rubyinfinite (same as Python)arithmetic
JavaScript Number32 bits (operand is truncated to int32 first)arithmetic with >>, logical with >>>
JavaScript BigIntinfinitearithmetic only (no >>>)
Bash, Zsh64-bit signedarithmetic
PowerShell32 or 64 depending on typearithmetic

The pattern: anything with a fixed-width type has a sensible NOT. Anything with arbitrary-precision integers (Python, Ruby, JavaScript BigInt) treats NOT as infinitely-wide two’s complement and requires an explicit mask to recover the byte or word view that the embedded world expects.

Related concepts

  • Two’s complement: how negative integers are encoded as bit patterns and why ~x equals -(x+1) for any fixed-width signed type.
  • Endianness: byte order for multi-byte values in memory. 0x1234 may be stored as 12 34 (big-endian) or 34 12 (little-endian).
  • Hamming weight: the count of set bits in a value. Reachable in most languages as popcount, bitCount, or bit_count.
  • Bit fields and packed structs: C and C++ syntax for naming individual bit ranges inside a single integer.
  • De Bruijn sequences: a technique for finding the lowest set bit in constant time using a small lookup table.