less_retarded_wiki/binary.md
Miloslav Ciz 2dda017fde Update
2022-04-13 21:22:00 +02:00

34 lines
7 KiB
Markdown

# Binary
Binary refers to to having two choices; in [computer science](compsci.md) binary refers to the base 2 numeral system, i.e. a system of writing numbers with only two symbols, usually [1](one.md)s and [0](zero.md)s. Binary is used in computers because this system is easy to implement in electronics (a switch can be on or off, i.e. 1 or 0; systems with more digits were tried but unsuccessful, they failed miserably in reliability). The word *binary* is also sometimes used as a synonym for a native [executable](executable.md) program.
One binary digit can be used to store exactly 1 [bit](bit.md) of [information](information.md). So the number of places we have for writing a binary number (e.g. in computer memory) is called a number of bits or bit **width**. A bit width *N* allows for storing 2^N values (e.g. with 2 bits we can store 4 values: 0, 1, 2 and 3).
At the basic level binary works just like the [decimal](decimal.md) (base 10) system we're used to. While the decimal system uses powers of 10, binary uses powers of 2.
For **example** let's have a number that's written as 10135 in decimal. The first digit from the right (5) says the number of 10^(0)s (= 1) in the number, the second digit (3) says the number of 10^(1)s (= 10), the third digit (1) says the number of 10^(2)s (= 100) etc. Similarly if we now have a number **100101** in binary, the first digit from the right (1) says the number of 2^(0)s (= 1), the second digit (0) says the number of 2^(1)s (= 2), the third digit (1) says the number of 2^(2)s (=4) etc. Therefore this binary number can be **converted to decimal** by simply computing 1 * 2^0 + 0 * 2^1 + 1 * 2^2 + 0 * 2^3 + 0 * 2^4 + 1 * 2^5 = 1 + 4 + 32 = **37**.
To **convert from decimal** to binary we can use a simple [algorithm](algorithm.md) that's derived from the above. Let's say we have a number *X* we want to write in binary. We will write digits from right to left. The first (rightmost) digit is the remainder after integer division of *X* by 2. Then we divide the number by 2. The second digit is again the remainder after division by 2. Then we divide the number by 2 again. This continues until the number is 0. For example let's convert the number 22 to binary: first digit = 22 % 2 = **0**; 22 / 2 = 11, second digit = 11 % 2 = **1**; 11 / 2 = 5; third digit = 5 % 2 = **1**; 5 / 2 = 2; 2 % 2 = **0**; 2 / 2 = 1; 1 % 2 = **1**; 1 / 2 = 0. The result is **10110**.
TODO: operations in binary
In binary it is very simple and fast to divide and multiply by (powers of) 2, just as it is simply to divide and multiple by (powers of) 10 in decimal (we just shift the radix point, e.g. the binary number 1011 multiplied by 4 is 101100, we just added two zeros at the end). This is why as a programmer **you should prefer working with powers of two**.
Binary can be very easily converted to and from [hexadecimal](hexadeciaml.md) and [octal](octal.md) because 1 hexadecimal (octal) digit always maps to exactly 4 (3) binary digits. E.g. the hexadeciaml number F0 is 11110000 in binary.
We can work with the binary representation the same way as with decimal, i.e. we can e.g. write negative numbers such as -110101 or [rational numbers](rational_number.md) such as 1011.001101. However in a computer memory there are no other symbols than 1 and 0, so we can't use extra symbols such as *-* or *.* to represent such values. So if we want to represent more numbers than non-negative integers, we literally have to only use 1s and 0s and choose a specific **representation**, or **format** of numbers -- there are several formats for representing e.g. [signed](signed.md) (potentially negative) or rational numbers, each with pros and cons. The following are the most common number representations:
- **[two's complement](twos_complement.md)**: Allows storing integers, both positive, negative and zero. It is **probably the most common representation** of integers because of its great advantages: basic operations (+, -, *) are performed exactly the same as with "normal" binary numbers, and there is no negative zero (which would be an inconvenience and waste of memory). Inverting a number (from negative to positive and vice versa) is done simply by inverting all the bits and adding 1. The leftmost bit signifies the number's sign (0 = +, 1 = -).
- **[sign-magnitude](sign_magnitude.md)**: Allows storing integers, both positive, negative and zero. It's pretty straightforward: the leftmost bit in a number serves as a sign, 0 = +, 1 = -, and the rest of the number is the distance from zero in "normal" representation. So e.g. 0011 is 3 while 1011 is -3. The disadvantage is there are two values for zero (positive, 0000 and [negative](negative_zero.md), 1000) which wastes a value and presents a computational inconvenience, and operations with these numbers are more complicated and slower (checking the sign requires extra code).
- **[one's complement](ones_complement.md)**: Allows storing integers, both positive, negative and zero. The leftmost bit signifies a sign, in the same way as with sign-magnitude, but numbers are inverted differently: a positive number is turned into negative (and vice versa) by inverting all bits. So e.g. 0011 is 3 while 1100 is -3. The disadvantage is there are two values for zero (positive, 0000 and [negative](negative_zero.md), 1111) which wastes a value and presents a computational inconvenience, and some operations with these numbers may be more complex.
- **[fixed point](fixed_point.md)**: Allows storing [rational numbers](rational_number.md) (fractions), i.e. numbers with a radix point (such as 1101.011), which can also be positive, negative or zero. It works by supposing a radix point at some fixed position in the binary representation, e.g. if we have an 8 bit number, we may consider 5 leftmost bits to represent the whole part and 3 rightmost bits to be the fractional part (so e.g the number 11010110 represents 11010.110). The advantage here is extreme simplicity (we can use normal integer numbers as fixed point simply by imagining a radix point). The disadvantage may be low precision and small range of representable values.
- **[floating point](float.md)**: Allows storing [rational numbers](rational_number.md) in great ranges, both positive, negative and zero, plus some additional values such as [infinity](infinity.md) and *[not a number](nan.md)*. It allows the radix point to be shifted which gives a potential for storing extremely big and extremely small numbers at the same time. The disadvantage is that float is extremely complex, [bloated](bloat.md), wastes some values and for fast execution requires a special hardware unit (which most "normal" computers nowadays have, but are missing e.g. in some [embedded systems](embedded.md)).
As anything can be represented with numbers, binary can be used to store any kind of information such as text, images, sounds and videos. See [data structures](data_structure.md) and [file formats](file_format.md).
## See Also
- [bit](bit.md)
- [hexadecimal](hexadeciaml.md)
- [data structure](data_structure.md)
- [data type](data_type.md)