All values of simple data types (sometimes called elementary or primitive) are atomic, that is, they have no internal structures. In this paragraph, we will consider all simple types, except for the subroutine, since it makes sense to discuss it together with the concept of a subroutine.

## Arithmetic Data Types

In computers, these data types represent numbers, so are really basic. As we have noted, in some languages (JavaScript) there is the only numeric type (Number) that represents all valid numbers. From the point of view of simplifying programs, this is, of course, convenient, but most industrial programming languages share arithmetic types into two types: integer (for representing integer values) and real (to represent numbers with a fractional part).

The main reason for this is that the representation of integers and real numbers in modern computers is different, different and set of operations. For example, the operations of adding integers and real numbers represented by different machine instructions. The nomenclature itself machine operations on integers and real numbers differs (for example, there are no bitwise operations for real numbers).

The implementation of operations on real numbers is more difficult from a hardware point of view view, therefore, in a number of architectures, real numbers can generally absent. In order for the programmer to take into account these nuances, many languages (including Pascal, C++, Java, C#) separate numeric types into two kind.

### Versatility.

Pascal provides the only

integer data type – integer. This is quite enough for an educational programming language, but is unacceptable in industrial programming. The C++, Java, and C# languages provide a generic integer type nomenclature that matches most modern architectures. These languages define single-byte integers (char in C++, byte in Java and C#), short integers (short), basic integers (int), long integers (long).

### Unsigned types.

Virtually all computer architectures support unsigned integer types, that is, integer types that contain only non-negative values, in addition to signed integers. This is due to the need to perform operations on addresses in machine programs.

Addresses are represented by an unsigned integer type (recall that an address is a zero-based memory location number). Operations on addresses called address arithmetic. The second reason for using unsigned numbers is that when the same size, the maximum value of an unsigned type is greater than the maximum value of a signed type (because you don’t need to store sign information).

In case the range of integer values is small, using the unsigned type sometimes necessary. The Java language does not contain unsigned types, which simplifies the implementation of the JVM and avoids a number of problems associated with the reliability of programs (see. below). The C++ and C# languages contain signed and unsigned variants for each integer type size. First of all, this is dictated by the requirement of universality.

### Performance.

Pascal and C++ do not fix the representation of an integer type. The size and range of values are implementation defined. This is due to the fact that these languages were implemented for a large number of machine architectures that differed significantly in the representation of numbers.

Fixing the view would give an unreasonable advantage to a particular architecture, since implementations on other architectures would be more complex and less efficient. The C++ language doesn’t even capture the view single-byte char. Depending on the implementation, it can be either signed (signed char) or unsigned (unsigned char).

### Reliability.

The reliability of language constructs is determined by the fact that to what extent these constructions protect the programmer from accidental errors. The presence of unsigned types reduces the reliability of working with integers.

That loop will never end because the loop variable i is always is non-negative. The problem is that in most machine architectures integer addition and subtraction operations do not generate an error when result is out of range. The decision about whether the value of the operation is correct, is the responsibility of the programmer

In the block following the checked keyword, all integer operations are checked for correctness, so when overflows (when trying to subtract 1 from an unsigned null value) an error is generated. Of course, the execution time of operations increases, so By default, operations are not controlled. Note that in the Java language it is simply impossible to make such a mistake. Another source of possible errors when working with integers types – conversions of values of one type to values of another type.