3.3 Numeric data types
From the moment we open our eyes every morning, we deal with numbers almost every hour: from 6:30 on the alarm clock to the 216 bus to work, from the news that the house price fell to 100 yuan per square meter to go home to buy vegetables when the tomato 3.5 yuan a catty. We live in a world full of numbers. The program is the description and expression of the real world, and there will be many numbers to express. To do this, C + + provides a rich variety of numeric data types, from integers to decimals, from single-precision floating-point numbers to double-precision floating-point numbers, from signed numbers to unsigned numbers. With these numeric data types, we can define various variables to represent the various numbers in the real world.
3.3.1 Integer Numeric type
In the real world, the most common numbers are all kinds of large and small integers, whereas in C + + we use integer numeric types to represent real-world integers. The integer numeric type is divided into the following four types, depending on the amount of memory resources consumed by these data types and the range of values to be taken.
1. Basic type
Its type specifier is int (integer), which accounts for 4 bytes in memory, ranging from 2147483648 to 2147483647, which basically contains our most common integers to satisfy our need to express integers in the program. At the same time, because it is an integral type supported by the CPU, it is processed the fastest. Therefore, int is the most common type of integer value we use.
Special note: The number of bytes in the data type may have different values in different environments
It is important to note that the number of bytes of memory that we are discussing here in the various data types is just the number of bytes in the typical case (32-bit operating system, 32-bit mainstream compiler). In some special environments (64-bit operating systems, special compilers), the number of bytes consumed by various data types may vary. So, the best way to get the number of bytes that a data type occupies in the current environment is to use the sizeof keyword to dynamically calculate its actual number of bytes instead of using a fixed number of bytes. Specific methods, you can refer to the introduction of sizeof in the following article.
2. Short integer type
Sometimes, we need to express the whole number is only in a relatively small range, for example, we want to express a student's performance, the minimum can be 0, and the largest can only to 100, if still use int this value range than the large data type to represent, it seems a bit of waste of resources. The creation of a conservation-minded society is now being advocated, and the C + + world is no exception. To represent such an integer with a relatively small range of values, C + + provides a short integer data type with a type specifier of either a shorter or a brief int, with only half of the bytes of memory, that is, two bytes. Naturally, the range of values is correspondingly reduced from 32768 to 32767, which we can use to express the common values of integers in life. However, with respect to the type of int, the short type is slower to process, and the memory is relatively inexpensive, so we tend to sacrifice space for performance and more use int to replace the short type.
3. Long Integer type
In some cases, we don't know exactly how big an integer we need to express, it could be thousands of, or maybe hundreds of millions of. In this case, we always want to get a maximum integer value type supported by the current platform to avoid errors caused by too small a range of values. In C + +, we use a long integer to represent the largest integer numeric type supported by the current platform natively. Its type specifier is a long or long int. On a 32-bit platform, it consumes 4 bytes of memory and has the same value range as int. On a 64-bit platform, it occupies 8 bytes of memory, and the range of values is correspondingly increased to appalling from 9223372036854775808 to 9223372036854775807, which definitely satisfies our need for an integer range.
4. Long-length integer
In C + +, in order to represent some particularly large integers in the real world, such as the total number of planets in a particular galaxy, we also need to use a larger range of long integer types. Its type specifier is a long long or a long long int, which occupies 8 bytes in memory. Its value range is astronomical, so it is only more used in special scientific calculations such as astronomical calculations.
In addition, these integer data types can be decorated with keyword unsigned or signed to form unsigned or signed integer data types. The so-called unsigned, refers to whether these values in memory of the first bit is used to indicate a positive or negative symbol or to indicate a value. By default, the integer data type described above is signed, and as long as the unsiged keyword is preceded by its type specifier, it becomes the corresponding unsigned integer data type.
int a; // default is signed int type
signed short b; // signed short type
unsighed long c; // unsigned long type
The various unsigned types occupy the same amount of memory space as the corresponding signed type. However, because unsigned types omit the sign bit, they cannot represent negative numbers, and accordingly, the range of positive numbers that it can represent expands to the original one-fold. When we know beforehand that the integers to be represented do not have negative numbers, you can use unsigned to decorate an integral numeric type so that it becomes an unsigned data type, extending its range of values on a positive number. Table 3-3 lists the various integer numeric data types, range of values, number of bits, and usage rules in C + + on a typical 32-bit platform.
Table 3-3 Integer numeric types
Data type |
Number of digits |
Range of values |
Usage rules |
Int |
32 |
-2147483648 ~ 2147483647 |
The most common, and also the fastest processing of integer numeric types, used to represent common integer values |
Signed int |
32 |
-2147483648 ~ 2147483647 |
is equivalent to the int type on use, so it is rarely used, and is basically directly using the int type |
unsigned int |
32 |
0 ~ 4294967295 |
An unsigned int type that can only represent a positive integer. You can use an unsigned data type when you want to represent an integer that has only a positive value |
Short int |
16 |
-32768 ~ 32767 |
Short, usually abbreviated, to represent a small range of integers to conserve memory resources, but processing speed is reduced |
Signed Short int |
16 |
-32768 ~ 32767 |
— |
unsigned short int |
16 |
0 ~ 65535 |
— |
Long int |
32 |
-2147483648 ~ 2147483647 |
Usually abbreviated as long, which represents the maximum integer data type supported by the CPU on the current platform. On a 32-bit platform, the range of values for long and int is the same, except that they differ on 64-bit operating systems, which requires attention when developing cross-platform applications |
Signed Long int |
32 |
-2147483648 ~ 2147483647 |
— |
unsigned long int |
32 |
0 ~ 4294967295 |
— |
Long Long int |
64 |
-9223372036854775808 ~ 9223372036854775807 |
An integer longer than long, we don't have to count how many bits it has, just know that when you want to represent a large, large integer, you can use it |
Learn more: Use the sizeof weight meter for data type weight
People in the real world, regardless of height, have a weight, and people decide what size to wear according to their weight, whereas in the C + + world, all types of data also have a weight, and the data type of weight determines how many bytes of memory it takes. The number of bytes of memory consumed by a data type, that is, its weight.
Why do we need to know the weight of the data type? We often need to know the number of bytes of memory used by the data type in order to read and write access to the data through direct manipulation of the memory, so that we can allocate the appropriate memory resources to that data, just as we want to make clothes for a person, first to know his height. For example, we want to dynamically request a memory to hold 1024 Long data, then we need to calculate the total number of bytes of memory resources to be stored according to the amount of memory consumed by each type of long data. Although we know that the number of bytes of long is 4 bytes Most of the time, we cannot use the magic number in the program directly, so a number that does not know where it comes from will make the program's maintainability worse; The number of bytes consumed by the data type is the same as the weight of the human body, which varies depending on the environment, and not all platforms have a long type of 4 bytes. If we use a fixed number 4来 in the program to represent the number of bytes of the Long data type, the program may run normally on some platforms, but when the program is ported to another platform, it is possible that an error will occur because of the different number of bytes in the Long data type. In order to improve the maintainability of the program and ensure the portability of the program, we must dynamically obtain the number of bytes of data type on the current platform in the code, and finally calculate the total amount of memory resources required.
All of these questions about the number of bytes of data type can be easily resolved once and for all using the sizeof data type scale that C + + provides to us. sizeof is actually an operator in C + + that can manipulate a data type or a variable or array of that data type to get the number of bytes of memory that the type or variable (array) actually occupies. For example, when we use the memset () function to clear 0 of an array, it is commonly used to calculate the number of bytes in this array:
#include <cstring> // Introduce the header file where the memset () function is located
//…
// define the array
int res [1024];
// Use sizeof to calculate the number of bytes occupied by res
memset (res, 0, sizeof (res));
Here, when we use the memset () function to clear the array res, the first parameter is the array name, which is the first address of the array, the second parameter is the initial value, usually 0, and the third parameter is used The number of bytes occupied by the res array calculated by the sizeof keyword. Fortunately, there is a sizeof scale, otherwise we will write more complicated "1024 * 4" here. Although this complex form can also achieve the purpose of calculating the volume of the array, it is very error-prone and has no portability. This is why sizeof scales are loved by programmers.
The sizeof brand data type scale not only can get the weight of the built-in data type (for example, int, long, double, etc.), it can also get the number of bytes occupied by custom structures or classes And the number of bytes added). E.g:
// define a structure
struct Human
{
char cName [3]; // 3 bytes
// char pad; // due to byte alignment, the compiler fills in one byte
int nAge; // 4 bytes
};
// Declare a structure variable
Human huZengmei;
// The number of bytes in the output structure is 8, including one byte added due to byte alignment, that is, 3 + 1 + 4 = 8
The number of bytes occupied by cout << "Human structure is:" << sizeof (Human) << endl;
// The number of bytes of the output structure variable is the same as the number of bytes of the structure
cout << "The number of bytes occupied by the Human object is:" << sizeof (huZengmei) << endl;
The sizeof brand weight scale is so easy to use, it should be used wherever you need to know the memory space occupied by a certain data type or variable (including array), for example, use the memset () function to clear the array, according to a certain The number of bytes occupied by the basic data type determines whether the current hardware platform is 32-bit or 64-bit, etc., in order to avoid the maintainability and portability problems that may be caused by manually specifying the number of bytes of the data type.
Figure 3-2 sizeof brand scale
3.3.2 Floating-point numeric types
The numbers in real life, in addition to the integer 216 representing the number of bus routes, are more like the decimal 3.5 representing the price of tomatoes. In C ++, we use floating-point numeric types to represent decimals. According to the different value ranges, floating-point numeric types in C ++ can be divided into three types: single-precision, double-precision, and long double-precision.
1. Single-precision type
Its type specifier is float. The single-precision floating-point numeric type occupies 4 bytes of memory space, and its value range is -3.4E + 38 ~ + 3.4E + 38. It should be noted here that because floating-point numeric types (including the following double and long double types) cannot accurately represent zero values, their value ranges are actually not continuous. For the positive and negative parts. Due to the limitation of the mechanism for storing floating-point numbers by computers, when floating-point numbers are used to represent floating-point numbers, they can be guaranteed to be accurate to at least 6 significant digits before and after the decimal point and up to 7 significant digits. E.g:
float fPrice = 3.5; // The variable fPrice of float type represents tomatoes 3.5 yuan a catty
Know more: Why are decimals called floating point in C ++?
In C ++, we refer to decimals as floating-point numbers, and the data types that represent decimals as floating-point numeric types. Everyone here will definitely ask: Why are decimals called floating point numbers? What does "floating" mean?
All this has to do with the way decimals are expressed in C ++. The so-called floating point is relative to fixed point. For example, we want to express these two decimals in C ++:
100000000000.0
0.000000000001
If the fixed point (fixed decimal point) expression is used, we need to save it in the following form:
100000000000.000000000000
000000000000.000000000001
In this way, we have to save the data on each bit originally. Some of these data are meaningless for the value and precision of decimals, but instead waste precious storage resources. In order to solve this problem, C ++ uses a new way of saving: express the numbers in the form of exponents, and save the significant digits and exponents of each digit. In this way, the two numbers above can be saved as follows:
Decimal 1 Index 11 (decimal point moved 11 places to the left)
Decimal 1 exponent -12 (decimal point moved 12 places to the right)
Through the movement of the decimal point position, we only need to save the significant digit of the decimal point and the position of the decimal point movement, and we can save the entire number in a more concise way. Because the decimal point in this expression is floating, the decimal point is also called a floating point number.
2. Double precision type
The type specifier is double. The double-precision floating-point numeric type occupies 8 bytes of memory space, which is double (double) times the single-precision floating-point numeric type. E + 308, at the same time, its precision is also higher, it can be accurate to 15 significant digits before and after the decimal point, up to 16 digits. E.g:
double fD = 0.0000003; // use a double type variable to represent the diameter of mycoplasma cells
3. Long double precision type
The type specifier is long double. The long double-precision floating-point numeric type occupies 12 bytes of memory space, and its numeric range can reach -1.2E + 4932 ~ 1.2E + 4932 at the astronomical level. Therefore, this type is more used in scientific calculations. , Less commonly used in daily development.
Table 3-4 lists the data type, number of digits, exact number of digits, value range, and usage rules for floating-point numeric values on a typical 32-bit platform.
Table 3-4 Floating-point numeric types
Data type |
Number of digits |
Valid numbers |
Range of values |
Usage rules |
Float |
32 |
6-7 |
-3.4E+38 ~ 3.4E+38 |
If the number of floating-point numbers to represent is not particularly large, the accuracy requirements are not very high, such as our daily life encountered in the various decimals, you can use the float type to represent, not only to meet the needs can also save memory space, improve performance |
Double |
64 |
15-16 |
-1.7E+308 ~ 1.7E+308 |
If you want to represent a large number of floating-point numbers, or high precision requirements, you can use a double type to represent, although more memory space, but can guarantee the value range and data precision |
Long double |
96 |
18-19 |
-1.2E+4932 ~ 1.2E+4932 |
If you want to represent astronomical figures, use it. |
|
|
|
|
|
|
Know more: How to generate random numbers?
The so-called random number, popularly speaking, is generated by a computer by a certain random number algorithm, according to a certain pattern distribution (average distribution or normal distributions) within a certain size range of numbers. In programming, random numbers are widely used in testing, gaming, simulation, and security. So, mastering the ways of generating random numbers is also an essential skill for us to develop with C + +.
In c++11, the generation of a random number needs to be accomplished by two parts of the random engine object and the distribution (distribution) object. Among them, the distribution object is responsible for the range and distribution of random numbers. For example, using the uniform_int_distribution distribution means that the random numbers generated by the engine are evenly distributed within a range, whereas using the normal_distribution distribution means that these random numbers are normally distributed in a range. Accordingly, the engine object is responsible for generating corresponding random numbers based on the range and distribution of values determined by the distribution object. Once we have determined that the random number produces the desired engine object and the distribution object in the program, we can use the engine object as a parameter and call the function object of the distribution object to get the random number we need. For example, the creation of a website login verification code requires a random number:
// Introduce the random number engine and the header file where the distribution is located
#include <random>
#include <iostream>
// Use the std namespace
using namespace std;
int main ()
{
// Define a default random number engine
default_random_engine reng;
// Build an average distribution from 0 to 25
uniform_int_distribution <int> uni_dist (0,25);
// Use random_device to set the seed of the random number engine,
// To prevent the same pseudo-random number sequence from being generated every time
random_device rnd_device;
reng.seed (rnd_device ());
// A total of 4 verification codes
const int n = 4;
char code [n]; // character array to store verification code
// Prompt for verification code
cout << "Please enter the following verification code:" << endl;
// Generate 4 verification code alphabet characters using for loop
for (int i = 0; i <n; ++ i)
{
// uni_dist (reng) means to let the reng engine be distributed according to uni_dist,
// Generate random numbers with values evenly distributed between 0 and 25
// Then shift backwards on the basis of ‘A’, you get a random verification code alphabetic character
code [i] = ‘A‘ + uni_dist (reng);
// output verification code alphabetic characters
cout << code [i];
}
//…
return 0;
}
In this program, we first introduced the C + + standard library on the random number of the header file <random>, and then we can define the corresponding random number engine objects (Reng) and distribution Objects (uni_dist), while defining the distribution of objects, we are in the form of constructor parameters , the range of the random number is determined. With them, you can use the engine object Reng as a parameter, call the Uni_dist distribution object This function object, and finally get what we need in the range of 0 and 25 of the average distribution of random numbers. Here, we also take advantage of the character of the continuous distribution of alphabetic characters in the ASCII table, and on the basis of the characters ' a ', with a random number, we get the random alphabetic characters we want at the end. It is important to note that before generating a random number, we have to set the random seed with the seed () function of the engine object, otherwise, the sequence of random numbers produced by each run is the same, so it loses its random meaning.
In addition, the program only uses random numbers to generate CAPTCHA characters, and then we need to receive input from the user and compare it with the current verification code to determine if the user input is correct. This work is left to everyone after learning the content behind (various control structures, string processing, etc.), to do it yourself. I believe you will soon be able to do this.
------->
Please look forward to the following episode: does he really love me? 3.4 Boolean type
Hello, C + + (9) Take the 216 bus to buy 3.5 yuan a catty of tomato--c++ how to express various numerical data 3.3 numeric data types