Understanding hexadecimals and bytes in C#

30,177

Solution 1

Hexadecimal is base 16, so instead of counting from 0 to 9, we count from 0 to F. And we generally prefix hex constants with 0x. Thus,

Hex      Dec
-------------
0x00  =  0
0x09  =  9
0x0A  =  10
0x0F  =  15
0x10  =  16
0x200 =  512

A byte is the typical unit of storage for values on a computer, and on most all modern systems, a byte contains 8 bits. Note that bit actually means binary digit, so from this, we gather that a byte has a maximum value of 11111111 binary. That is 0xFF hex, or 255 decimal. Thus, one byte can be represented by a minimum of two hexadecimal characters. A typical 4-byte int is then 8 hex characters, like 0xDEADBEEF.

RGB values are typically packed with 3 byte values, in that order, RGB. Thus,

R=255 G=0 B=0    =>  R=0xFF G=0x00 B=0x00  =>  0xFF0000  or #FF0000 (html)
R=66  G=0 B=248  =>  R=0x42 G=0x00 B=0xF8  =>  0x4200F8  or #4200F8 (html)

For my hex calculations, I like to use python as my calculator:

>>> a = 0x427FB
>>> b = 700
>>> a + b
273079
>>>
>>> hex(a + b)
'0x42ab7'
>>>
>>> bin(a + b)
'0b1000010101010110111'
>>>

For the RGB example, I can demonstrate how we could use bit-shifting to easily calculate those values:

>>> R=66
>>> G=0
>>> B=248
>>>
>>> hex( R<<16 | G<<8 | B )
'0x4200f8'
>>>

Solution 2

Base-16 (also known as hex) notation is convenient because you can fit four bits in exactly one hex digit, making conversion to binary very easy, yet not requiring as much space as a full binary notation. This is useful when you need to represent bit-oriented data in a human-readable form.

Learning hex is easy - all you need to do is memorizing a short table of 16 rows defining hex-to-binary conversion:

0 - 0000
1 - 0001
2 - 0010
3 - 0011
4 - 0100
5 - 0101
6 - 0110
7 - 0111
8 - 1000
9 - 1001
A - 1010
B - 1011
C - 1100
D - 1101
E - 1110
F - 1111

With this table in hand, you can easily convert hex strings of arbitrary length to their corresponding bit patterns:

0x478FD105 - 01000111100011111011000100000101 

Converting back is easy as well: group your binary digits by four, and use the table to make hex digits

0010 1001 0100 0101 0100 1111 0101 1100 - 0x29454F5C

Solution 3

The answer to the actual question posted ("Why do we use things like FF, is it to compensate for the base 10 system to get a number like 10?") is this: Computer use bits, that means either 1 or 0.

The essence is similar to what Lee posted and called "positional notation". In a decimal number, each position in the number refers to a power of 10. For example, in the number 123, the last position represents 10^0 -- the ones. The middle position represents 10^1 -- the tens. And the first is 10^2 -- the hundreds. So the number "123" represents 1 * 100 + 2 * 10 + 3 * 1 = 123.

Numbers in binary use the same system. The number 10 (base 2) represents 1 * 2^1 + 0 * 2^0 = 2.

If you want to express the decimal number 10 in binary, you get the number 1010. That means, you need four bits to represent a single decimal digit.

But with four bits you can represent up to 16 different values, not just 10 different values. If you need four bits per digit, you might as well use numbers in the base 16 instead of only base 10. That's where hexadecimal comes into play.


Regarding how to convert ARGB values; as been written in other replies, converting between binary and hexadecimal is comparatively easy (4 binary digits = 1 hex digit).

Converting between decimal and hex is more involving and at least to me it's been easier (if i have to do it in my head) to first convert the decimal into binary representation, and then the binary number into hex. Google probably has tons of how-tos and algorithms for that.

Solution 4

In decimal, each digit is weighted 10 times more than the one to the right, for example the '3' in 32 is 3 * 10, and the '1' in 102 is 1 * 100. Binary is similar except since there are only two digits (0 and 1) each bit is only weighted twice as much as the one to the right. Hexadecimal uses 16 digits - the 10 decimal digits along with the letters A = 10 to F = 15.

An n-digit decimal number can represent values up to 10^n - 1 and similarly an n-digit binary number can represent values up to 2^n - 1.

Hexadecimal is convenient since you can express a single hex digit in 4 bits since 2^4 = 16 possible values can be represented in 4 bits.

You can convert binary to hex by grouping from the right 4 bits at a time and converting each group to the corresponding hex. For example 1011100 -> (101)(1100) -> 5C

The conversion from hex to binary is even simpler since you can simply expand each hex digit into the corresponding binary, for example 0xA4 -> 1010 0100

Share:
30,177
Daniel Minnaar
Author by

Daniel Minnaar

If the facts don't fit the theory, change the facts.

Updated on June 28, 2020

Comments

  • Daniel Minnaar
    Daniel Minnaar almost 4 years

    I seem to lack a fundemental understanding of calculating and using hex and byte values in C# (or programming in general).

    I'd like to know how to calculate hex values and bytes (0x--) from sources such as strings and RGB colors (like how do I figure out what the 0x code is for R255 G0 B0 ?)

    Why do we use things like FF, is it to compensate for the base 10 system to get a number like 10?

    • Lee
      Lee over 11 years
      Hex is convenient since you can express a single hex digit in 4 bits, so a byte (e.g. 0xFF = 11111111) can be expressed in two hex digits.
    • PMC
      PMC over 11 years
      Open calculator in Windows > Type in digits and change from dec to hex to binary and have a play with different numbers