Positional numeral system, also known as carry system, base system, positional notation, place-value notation, or positional numeral system, is a numeral system that can represent all natural numbers using a finite set of symbols. The number of symbols available in a positional system is called its radix or base. A positional system with radix is called the -ary system (); for example, the decimal system we use most often generally uses only the ten symbols 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 for notation. Carrying is the operation of “when a digit in some position reaches the base, set it to 0 and increment the digit in the next higher position.”
In general, we write a number in base as , , , , and so on. If the base is implicit from the context, the subscript may be omitted. Note that here is not the product of numbers, but a sequence.
For a base- number , its value is ; for a number , suppose its representation in base is . Then:
where .
The length of the representation of in base is .
We generally use a decimal point “” to represent fractions1, a minus sign “” to represent negative numbers, and an overline over the final part of a decimal to represent an infinite repeating fraction. For readability, we may insert separators between groups of digits, such as spaces, , or '; for example, represents .
The positional systems commonly used in computers include binary, octal, and hexadecimal.
Conversion between positional systems
Decimal to other bases
We use binary as an example here; the principle is similar for other bases.
For the integer part, repeatedly divide the decimal number by until the quotient is , then take the digits of all remainders from bottom to top; these are the digits of the binary integer part. For the fractional part, multiply it by , take the integer part of the result, and then repeat the process with the fractional part obtained from the calculation until the fractional part is all . Finally, take the integer parts obtained in each calculation from top to bottom; these are the digits of the binary fractional part.
Example
Convert to a binary number.
Integer part:
Fractional part:
Therefore, .
Implementation
#include <algorithm>
#include <string>
// only non-negative
// 2 <= base && base <= 36
std::string from_dec(int x, int base) {
if (x == 0) return "0";
std::string res;
while (x) {
int r = x % base;
x /= base;
// Method 1
res.push_back(r < 10 ? '0' + r : 'A' + r - 10);
// Method 2
// const static std::string digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// res.push_back(digits[r]);
}
std::reverse(res.begin(), res.end());
return res;
}
Other bases to decimal
Again, we use binary as an example. To convert a binary number to a decimal number, simply multiply the value of each digit by , where is the position of the current digit and the units digit has position .
Example
Convert to a decimal number.
Thus, .
Implementation
#include <cctype>
#include <string>
// only non-negative
// 2 <= base && base <= 36
int to_dec(std::string const& s, int base) {
int res = 0;
for (char c : s) {
res *= base;
if (isdigit(c))
res += c - '0';
else if (isupper(c))
res += c - 'A' + 10;
else if (islower(c))
res += c - 'a' + 10;
}
return res;
}
Conversion among binary, octal, and hexadecimal
One octal digit can be represented by 3 binary digits (because ), and one hexadecimal digit can be represented by 4 binary digits (); the converse follows similarly.
Method of complements
See also: Ones' and two's complements
The method of complements is a method of representing negative numbers with positive numbers, so that subtraction can be computed using the same algorithms, circuits, or mechanical structures as addition with positive numbers. The method of complements is widely used in the design of calculators and computers to simplify their structure.
For an -digit base- number , its radix complement (also called the complement to ) is , while its diminished radix complement (also called the complement to , or simply the diminished complement) is . In binary, the radix complement is called the complement to (two's complement), also known as two's complement representation; the diminished radix complement is called the complement to (ones' complement), also known as one's complement representation; in decimal, the radix complement is also called the complement to (ten's complement), and the diminished radix complement is also called the complement to (nine's complement); other bases follow the same pattern.
For -digit base- numbers , when computing , we have the following methods (if the result exceeds digits, discard the higher digits):
- Consider the diminished complement of , and compute ; the diminished complement of this result is the answer.
- Consider the diminished complement of , and compute ; simply add one to obtain the answer.
- Consider the radix complement of , and compute ; the radix complement of this result is the answer.
- Consider the radix complement of , and compute ; this is the answer.
In addition, for a number in base , let . Then . Therefore, for an -digit number , if its radix-complement representation in base is , then is . This idea of “numbers with infinitely many digits” can be generalized to -adic numbers (-adic number).
Furthermore, we have an interesting theorem about complements and infinite repeating decimals:
Midy's theorem
Let be a positive integer and a positive prime. Suppose that the representation of in base is , where is the (shortest) repetend length. If is even2, let . Then is the diminished complement of , that is:
- ,
- .
More generally, if has a nontrivial factor , let . Then is a multiple of .
Example
For , we have:
- ,
- ,
- ,
- .
Proof
For the in the theorem, it is not difficult to see that and .
For an integer , let . We have
0<f(i)=0.\overline{a_{i+1}a_{i+2}\cdots a_{nk}a_1a_2\cdots a_i}<1 \implies 0<pf(i) $$ Note that $pf(i)\in\mathbf{N}_+$ and $pf(i)\equiv ab^i\pmod p$, so $pf(i)=ab^i\bmod p$. Let $S_n=\sum_{i=0}^{n-1}f(ik)=\sum_{i=0}^{n-1}0.\overline{a_{ik+1}a_{ik+2}\cdots a_{nk}a_1a_2\cdots a_{ik}}$. We can “exchange” some digits among the fractions (for example, $0.\overline{{\color{Orchid}{14}}{\color{RoyalBlue}{28}}{\color{YellowGreen}{57}}}+0.\overline{{\color{RoyalBlue}{28}}{\color{YellowGreen}{57}}{\color{Orchid}{14}}}+0.\overline{{\color{YellowGreen}{57}}{\color{Orchid}{14}}{\color{RoyalBlue}{28}}}=0.\overline{\color{Orchid}{141414}}+0.\overline{\color{RoyalBlue}{282828}}+0.\overline{\color{YellowGreen}{575757}}=0.\overline{\color{Orchid}{14}}+0.\overline{\color{RoyalBlue}{28}}+0.\overline{\color{YellowGreen}{57}}=14/99+28/99+57/99=1$), so\begin{aligned} S_n&=\sum_{i=0}^{n-1}0.\overline{a_{ik+1}a_{ik+2}\cdots a_{(i+1)k}}\ &=\sum_{i=0}^{n-1}a_{ik+1}a_{ik+2}\cdots a_{(i+1)k}/\left(b^k-1\right), \end{aligned}
pS_n=p\sum_{i=0}^{n-1}a_{ik+1}a_{ik+2}\cdots a_{(i+1)k}/\left(b^k-1\right)= \sum_{i=0}^{n-1} \left(ab^{ik}\bmod p\right),
\sum_{i=0}^{n-1}a_{ik+1}a_{ik+2}\cdots a_{(i+1)k}=\left(b^k-1\right)\frac{\sum_{i=0}^{n-1} \left(ab^{ik}\bmod p\right)}{p}.
If $p\mid \left(b^k-1\right)$, note that\left(b^k-1\right)a/p=a_1a_2\cdots a_k.\overline{a_{k+1}a_{k+2}\cdots a_{nk}a_1a_2\cdots a_k}-0.\overline{a_{1}a_{2}\cdots a_{nk}},
Then $a_{k+1}a_{k+2}\cdots a_{nk}a_1a_2\cdots a_k=a_{1}a_{2}\cdots a_{nk}$, and consequently $a_1a_2\cdots a_k=a_{k+1}a_{k+2}\cdots a_{2k}=\dots=a_{(n-1)k+1}a_{(n-1)k+2}\cdots a_{nk}$. Thus $0.\overline{a_1a_2\cdots a_l}=0.\overline{a_1a_2\cdots a_k}$, contradicting the definition of $l$, so $p\nmid \left(b^k-1\right)$. Hence there exists a positive integer $c=\dfrac{\sum_{i=0}^{n-1} \left(ab^{ik}\bmod p\right)}{p}$ such that\sum_{i=0}^{n-1}a_{ik+1}a_{ik+2}\cdots a_{(i+1)k}=c\left(b^k-1\right).
Corollary
For the above , we have
Generalized positional systems
In a standard positional system, the base is always a fixed positive number, and each digit is selected from different symbols to represent a nonnegative number (disregarding the decimal point and minus sign). In fact, many other numeral and positional systems have similar characteristics but do not fully satisfy the definition of a positional system. We call such systems generalized positional systems or non-standard positional numeral systems. Several common generalized positional systems are introduced below.
Bijective numeral systems
Standard positional systems cannot establish a bijection with the numbers they represent: for example, , , and represent the same number3, whereas a bijective numeral system can establish a bijection with the numbers it represents.
Bijective base () uses the set to represent each number uniquely, according to the following rules:
- The empty string represents ;
- A nonempty string represents the number .
For a positive number , suppose its representation in bijective base is . Then:
where .
For example, Microsoft Excel's column labels use bijective base .
In the bijective numeral system, we have the unary numeral system, in which a nonempty string consists only of s, and the length of the string is the number it represents.
As in the discussion of the method of complements, in bijective base with , let . Then , and therefore . Thus, if the representation of in bijective base is , then is .
Here are some properties of bijective base- numbers:
- There are numbers of length .
- When , the length of the representation of in bijective base is .
- When , if the representation of a number in base contains no , then its representation in base is the same as its representation in bijective base .
The code for converting bijective base to decimal is the same as the code for converting base to decimal. Below is a reference implementation for converting decimal to bijective base .
Implementation
#include <algorithm>
#include <string>
// only non-negative
// 1 <= base && base < 36
std::string from_dec_bi(int x, int base) {
std::string res;
while (x > 0) {
int q = (x + base - 1) / base - 1, r = x - q * base;
x = q;
// Method 1
res.push_back(r < 10 ? '0' + r : 'A' + r - 10);
// Method 2
// const static std::string digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// res.push_back(digits[r]);
}
std::reverse(res.begin(), res.end());
return res;
}
Signed-digit bases
Some positional systems allow negative numbers to occur as digits, such as balanced ternary.
Gray code
Main article: Gray code
Gray code is also called cyclic binary code or reflected binary code (reflected binary code, RBC). It is a special binary numeral system, commonly used for data checking.
Non-positive bases
We know that for a base- number , its value is . With a slight modification, we can define a base- number to represent , where . For example, . This positional system is called a negative-base system.
Similarly, we can define a complex-base system, such as a base system (quater-imaginary base, quater-imaginary numeral system). We can also define a non-integer base of numeration for the -expansion (-expansion) of real numbers.
Mixed-radix systems
In a standard positional system, the base corresponding to every digit is fixed, while a mixed-radix system allows each digit to correspond to a different base. The most common application of mixed-radix systems is timekeeping: hours use base , while minutes and seconds use base .
The number represented by in base is , while in a mixed-radix system it is , where is the base corresponding to .
In algorithmic competitions, the most common mixed-radix system is the factorial number system, whose numbers can be written as and whose value is 4. For applications of the factorial number system in algorithmic competitions, see Lehmer code/Cantor expansion.
Implementation (decimal to factorial number system)
#include <algorithm>
#include <string>
// only non-negative
std::string from_dec_factorial(int x) {
if (x == 0) return "0";
std::string res;
int base = 1;
while (x) {
int r = x % base;
x /= base++;
// Method 1
res.push_back(r < 10 ? '0' + r : 'A' + r - 10);
// Method 2
// const static std::string digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// res.push_back(digits[r]);
}
std::reverse(res.begin(), res.end());
return res;
}
Implementation (factorial number system to decimal)
#include <cctype>
#include <string>
// only non-negative
int to_dec_factorial(std::string const& s) {
int res = 0, base = s.size();
for (char c : s) {
res *= base--;
if (isdigit(c))
res += c - '0';
else if (isupper(c))
res += c - 'A' + 10;
else if (islower(c))
res += c - 'a' + 10;
}
return res;
}
Implementation in C++
For nonnegative numbers, C++ uses <前缀><数位><后缀> to represent an integer literal, where <数位> and <后缀> may both be empty. <后缀> indicates the type of the literal: for example, u or U indicates that the literal is unsigned, while l or L indicates that it is long, and so on. For <前缀>:
- When
<前缀>is0xor0X, it denotes a hexadecimal literal, and the characters in<数位>can only be selected from0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, A, b, B, c, C, d, D, e, E, f, F. For example,0x1234ABCDis ; - When
<前缀>is0, it denotes an octal literal, and the characters in<数位>can only be selected from0, 1, 2, 3, 4, 5, 6, 7. For example,01234567is ; 5 - When
<前缀>is1,2,3,4,5,6,7,8, or9, it denotes a decimal literal, and the characters in<数位>can only be selected from0, 1, 2, 3, 4, 5, 6, 7, 8, 9; - Since C++14, when
<前缀>is0bor0B, it denotes a binary literal, and the characters in<数位>can only be selected from0, 1. For example,0b11001010is .
References and notes
- Positional notation - Wikipedia
- Method of complements - Wikipedia
- Non-standard positional numeral systems - Wikipedia
- Bijective numeration - Wikipedia
- Midy's theorem - Wikipedia
- N3472 - Binary Literals in the C++ Core Language
Footnotes
-
Some regions use “” as the decimal point. ↩
-
When , the sequence of primes satisfying this condition in decimal is A028416. ↩
-
We call the s before the highest non- digit leading zeros (leading zero). Similarly, we can define trailing zeros (trailing zero). ↩
-
The base corresponding to is , and . Note that , so the representation of a number in the factorial number system is unique after leading zeros are removed. ↩
-
0is an octal literal. ↩