Previous article: Python Standard Library — 9. Built in types: logical value detection, Boolean operation, comparison

Next article: Python Standard Library — 11. Built in types: iterator type, sequence type

## Number type — int, float, complex

There are three different types of numbers: integers, floating-point numbers, and complex numbers. In addition, Boolean values are subtypes of integers. Integers have infinite precision. Floating point numbers are usually implemented by using double in C; the precision and internal representation of floating point numbers on the machine where your program runs can be found in sys.float? Info. The complex number includes the real part and the virtual part, which are represented by a floating-point number respectively. To extract these two parts from a complex Z, use z.real and z.imag. (the standard library contains additional numeric types, such as fragments for rational numbers and decimal for floating-point numbers with custom precision.)

Numbers are created from numeric literals or the results of built-in functions and operators. Unmodified integer literals, including hexadecimal, octal, and binary numbers, generate integers. Numeric literals that contain decimal or power operators generate floating-point numbers. Adding ‘J’ or ‘J’ to the end of a numeric literal generates an imaginary number (a complex number with a real part of zero), which you can add to an integer or floating-point number to get a complex number with a real part and an imaginary part.

Python fully supports mixed arithmetic: when a binary operator is used for operands of different number types, operands of “narrower” type will be expanded to the type of another operands, integers are narrower than floating-point numbers, and floating-point numbers are narrower than complex numbers. The same rules apply to the comparison of mixed type numbers. Constructors int(), float(), and complex() can be used to generate specific types of numbers.

All number types (except complex numbers) support the following operations, sorted in ascending order of priority (all number operations have higher priority than comparison operations):

evernotecid://D603D29C-DFBA-4C04-85E9-CCA3C33763F6/appyinxiangcom/23852268/ENResource/p19

Notes:

- Also known as integer division. The result value is an integer, but the result type is not necessarily int. The result of the operation is always rounded in the direction of negative infinity: 1 / / 2 is 0, (- 1) / / 2 is – 1, 1 / / (- 2) is – 1 and (- 1) / (- 2) is 0.
- Not available in the plural. Instead, use ABS () to convert to floating-point numbers when appropriate.
- Converting from floating-point numbers to integers is rounded or truncated as in C; see the math. Floor() and math. Ceil() functions for a complete definition of the conversion.
- Float also accepts the string “Nan” and “inf” with optional prefixes “+” or “-” for non numeric (Nan) and positive or negative infinity, respectively.
- Python defines pow (0, 0) and 0 * * 0 as 1, which is a common practice in programming languages.
- Accepted numeric literals include numbers 0 through 9 or any equivalent Unicode character (code point with Nd attribute).

See http://www.unicode.org/public… For a complete list of code points with Nd characteristics.

### Bitwise operation of integer type

Bitwise operations are only meaningful for integers. Calculating the result of bitwise operation is equivalent to using infinite number of binary symbol bits to perform operations on the complement of two.

The priority of binary bitwise operation is all lower than that of number operation, but higher than that of comparison operation; unary operation ~ has the same priority as other unary operation (+ and -).

This table is a bitwise operation list sorted in ascending priority order:

Notes:

- A negative shift is illegal and causes a valueerror to be raised.
- Shifting n bits to the left is equivalent to multiplying pow (2, n) without overflow detection.
- Shifting n bits to the right is equivalent to dividing pow (2, n) without overflow detection.
- Using a finite binary complement representation with at least one extra symbol extension bit (with a significant bit width of 1 + max (x.bit [length(), y.bit [length()) or more) to perform these calculations is sufficient to obtain the same result as if there were countless symbol bits.

### Additional methods for integer types

Int type implements numbers.integral abstract base class. In addition, it provides several other methods:

#### int.bit_length()

Returns the number of bits required to represent an integer in binary, excluding the sign bits and preceding zeros:

```
>>>
>>> n = -37
>>> bin(n)
'-0b100101'
>>> n.bit_length()
6
```

More precisely, if x is non-zero, then x.bit’length() is such that 2**(k-1) <= abs(x) < 2**The unique positive integer k of K. Similarly, when ABS (x) is small enough to have the correct rounding logarithm, k = 1 + int (log (ABS (x), 2)). If x is zero, x.bit’u length() returns 0.

Equivalent to:

```
def bit_length(self):
# binary representation: bin(-37) --> '-0b100101'
s = bin(self)
# remove leading zeros and minus sign
s = s.lstrip('-0b')
# len('100101') --> 6
return len(s)
```

3.1 new functions

#### int.to_bytes(length, byteorder, *, signed=False)

Returns an array of bytes representing an integer.

```
>>> (1024).to_bytes(2, byteorder='big')
b'\x04\x00'
>>> (1024).to_bytes(10, byteorder='big')
b'\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00'
>>> (-1024).to_bytes(10, byteorder='big', signed=True)
b'\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00'
>>> x = 1000
>>> x.to_bytes((x.bit_length() + 7) // 8, byteorder='little')
b'\xe8\x03'
```

Integers are represented by length bytes. Overflow error is raised if an integer cannot be represented by the given number of bytes.

The byteorder parameter determines the byte order used to represent integers. If byteorder is “big”, the highest byte is placed at the beginning of the byte array. If byteorder is “little”, the highest byte is placed at the end of the byte array. To request the native byte order on the host system, use sys.byteorder as the byte order value.

The signed parameter determines whether to use the complement of two to represent an integer. If signed is false and a negative integer is given, an overflow error is raised. The default value for signed is false.

3.2 new functions

#### classmethod int.from_bytes(bytes, byteorder, *, signed=False)

Returns the integer represented by the given byte array.

```
>>> int.from_bytes(b'\x00\x10', byteorder='big')
16
>>> int.from_bytes(b'\x00\x10', byteorder='little')
4096
>>> int.from_bytes(b'\xfc\x00', byteorder='big', signed=True)
-1024
>>> int.from_bytes(b'\xfc\x00', byteorder='big', signed=False)
64512
>>> int.from_bytes([255, 0, 0], byteorder='big')
16711680
```

The bytes parameter must be a bytes like object or an iterative object that generates bytes.

The byteorder parameter determines the byte order used to represent integers. If byteorder is “big”, the highest byte is placed at the beginning of the byte array. If byteorder is “little”, the highest byte is placed at the end of the byte array. To request the native byte order on the host system, use sys.byteorder as the byte order value.

The signed parameter indicates whether to use the complement of two to represent an integer.

3.2 new functions

### Additional methods for floating point types

The float type implements numbers.real abstract base class. Float also has the following additional methods.

#### float.as_integer_ratio()

Returns a pair of integers with a ratio exactly equal to the original floating-point number and a positive denominator. Infinite assembly raises overflow error and Nan raises valueerror.

#### float.is_integer()

Returns true if the float instance can be represented by a finite bit integer, otherwise false:

```
>>>
>>> (-2.0).is_integer()
True
>>> (3.2).is_integer()
False
```

Both methods support conversion to hexadecimal numeric strings. Because Python floating-point numbers are stored internally as binary numbers, the conversion between floating-point numbers and decimal number strings often results in minor rounding errors. The hexadecimal string allows for the precise representation and description of floating-point numbers. This is very useful for debugging and numerical work.

#### float.hex()

Returns a floating-point representation as a hexadecimal string. For a finite floating-point number, this representation will always contain leading X and trailing p-plus exponent.

#### classmethod float.fromhex(s)

Returns the class method of a floating-point number represented by the hexadecimal string s. The string s can have leading and trailing spaces.

Note that float. Hex () is an instance method and float. Fromhex () is a class method.

The hexadecimal string takes the form:

`[sign] ['0x'] integer ['.' fraction] ['p' exponent]`

The optional sign can be + or – integer and fraction are strings of hexadecimal numbers, and exponent is a decimal integer with optional leading characters. Case has no effect, there must be at least one hexadecimal number in integer or fraction. This syntax is similar to that described in section 6.4.4.2 of the C99 standard, and it is also used by Java 1.5 and above. In particular, the output of float. Hex() can be used as a hexadecimal floating-point numeric face value in C or Java code, while the hexadecimal numeric character string generated by the% a format character of C or double.tohexstring of Java is accepted by float. Fromhex().

Note that exponent is a decimal number, not a hexadecimal number, which gives the power of 2 to be multiplied by the coefficient. For example, the hexadecimal string 0x3.a7p10 represents a floating-point number (3 + 10. / 16 + 7. / 16**2) * 2.0**10 is 3740.0:

```
>>>
>>> float.fromhex('0x3.a7p10')
3740.0
```

Applying reverse conversion to 3740.0 results in another hexadecimal string representing the same value:

```
>>>
>>> float.hex(3740.0)
'0x1.d380000000000p+11'
```

### Hash operation of number type

For numbers x and y that may be of different types, when x = = y is required, it must have hash (x = = hash (y) (see the documentation of the \\\\\\\\\\\\\\\. In order to implement and ensure efficiency on various types of numbers (including int, float, decimal.decimal and fractions. Fraction), Python’s hash operation on number types is based on defining a unified mathematical function for any rational number, so the operation is available for all instances of int and fractions.fraction, as well as all limited instances of float and decimal.decimal. In essence, this function is given by P reduction with a fixed prime number P. The value of P can be accessed in Python in the form of the module property of sys.hash_info.

Cpython implementation detail: the current prime number setting is p = 2 on a 32-bit machine with C long**31 – 1 and P = 2 on machines with 64 bit C long**61 – 1。

The detailed rules are as follows:

- If x = m / N is a non negative rational number and N is not divisible by P, then hash (x) is defined as m * invmod (n, P)% P, where invmod (n, P) is the inverse of N mod P.
- If x = m / N is a non negative rational number and N can be divided by P (but M can’t), then n can’t be demodulated to P, and the above rules don’t apply; in this case, hash (x) is defined as the constant value sys.hash_info.inf.
- If x = m / N is a negative rational number, then hash (x) is defined as – hash (- x). If the result hash value is – 1, replace it with – 2.
- The specific values sys.hash.inf, – sys.hash.inf and sys.hash.nan are used as hash values for positive, negative and null values, respectively. (all nulls that can be hashed have the same hash value.)
- For a complex value Z, the hash (z.real) + sys.hash_info.imag
*Hash (z.imag) combines the hash values of real part and virtual part, and reduces the module2**(sys. Hash_info. Width – 1)). Similarly, if the result is – 1, replace it with – 2.**Sys.hash_info.width to make it in range (- 2**(sys.hash_info.width – 1), 2

To illustrate the above rules, here are some Python code examples equivalent to the built-in hash algorithm, which can be used to calculate the hash value of a rational number, a float, or a complex:

```
import sys, math
def hash_fraction(m, n):
"""Compute the hash of a rational number m / n.
Assumes m and n are integers, with n positive.
Equivalent to hash(fractions.Fraction(m, n)).
"""
P = sys.hash_info.modulus
# Remove common factors of P. (Unnecessary if m and n already coprime.)
while m % P == n % P == 0:
m, n = m // P, n // P
if n % P == 0:
hash_value = sys.hash_info.inf
else:
# Fermat's Little Theorem: pow(n, P-1, P) is 1, so
# pow(n, P-2, P) gives the inverse of n modulo P.
hash_value = (abs(m) % P) * pow(n, P - 2, P) % P
if m < 0:
hash_value = -hash_value
if hash_value == -1:
hash_value = -2
return hash_value
def hash_float(x):
"""Compute the hash of a float x."""
if math.isnan(x):
return sys.hash_info.nan
elif math.isinf(x):
return sys.hash_info.inf if x > 0 else -sys.hash_info.inf
else:
return hash_fraction(*x.as_integer_ratio())
def hash_complex(z):
"""Compute the hash of a complex number z."""
hash_value = hash_float(z.real) + sys.hash_info.imag * hash_float(z.imag)
# do a signed reduction modulo 2**sys.hash_info.width
M = 2**(sys.hash_info.width - 1)
hash_value = (hash_value & (M - 1)) - (hash_value & M)
if hash_value == -1:
hash_value = -2
return hash_value
```

Previous article: Python Standard Library — 9. Built in types: logical value detection, Boolean operation, comparison

Next article: Python Standard Library — 11. Built in types: iterator type, sequence type