Source

Numbers

Introduction to Numbers

Python offers a variety of different numeric types: integers, which are fast but limited in size; long integers, which are slower but can be of arbitrary size; floating-point numbers; and complex numbers.

The simplest and most basic type are integers, which are represented as a C long. Their size is therefore dependent on the platform you’re using; on a 32-bit machine, they can range from -2147483647 to 2147483647. Python programs can determine the highest possible value for an integer by looking at sys.maxint; the lowest possible value will usually be -sys.maxint - 1.

Long integers are an arbitrary-precision integer type. They’re slower than regular integers, but don’t have the size limitations. Long integer literals have the letter “L” as a suffix; a lowercase “l” is also legal, but should be avoided because it’s often difficult to distinguish a lowercase letter “l” from the numeral “1“. If integers and long integers are combined in an expression, the regular integer is converted to a long integer automatically:

2L + 3 5L  5L ** 100 7888609052210118054117285652827862296732064351090230047702789306640625L

Python’s floating point numbers are represented as C’s double type, and behave pretty much as you’d expect:

5.4 / 2.3 2.34782608696  6.4 * 2 12.8  7.5 % 5 2.5

In operations that mix floating-point numbers and integers, the integers will be converted to floating-point before computing the result, which will be left as a float.

Python also supports a complex number type. (It’s possible to compile the Python interpreter without complex numbers, but few people bother to do so; saving 20K of code isn’t that important.) Complex numbers are represented by a floating point constant with a suffix of “j“or “J” suffix, “j” being used to represent the square root of -1 in many engineering contexts.

1j * 1J (-1+0j)  (3 - 7j) + (2 + 1j) (5-6j)  (1 + 3j) / (2 - 4j) (-0.5+0.5j)

Note that an expression like 1 + 3j isn’t a constant, but an expression that adds two constants: 1 and 3j. This is a minor semantic quibble, whose major significance is that you should make liberal use of parentheses in complex expressions. 1+3j / 2-4j is not the same as (1+3j) / (2-4j), because the first expression will evaluate 3j/2 first.

Converting Numbers to and from Binary Data

Problem

You need to convert an integer value V to a 2-byte or 4-byte string representation. For example, the number 1 would be the bytes 0,1; 1956 would be 164, 7 because 1956 = 7 * 256 + 164. This is often needed when reading or writing binary data files, or implementing network protocols.

Solution

You can write code to perform the conversion by taking the low byte of V, shifting V down 8 bits and taking the low byte of the result, and so forth. However, the code is long and relatively slow:

s = ( chr( (V)        255 ) +
      chr( (V >> 8)   255 ) +
      chr( (V >> 16)  255 ) +
      chr( (V >> 24)  255 ) )

A faster and simpler solution uses the <<PythonModule struct>> module, which is intended for such conversions:

import struct
s = struct.pack('i', V )

To reverse the conversion, and go from a binary string to a tuple of integers, use struct.unpack():

byte, short = struct.unpack('BH', '\377\000\377\377')

Discussion

You’re not limited to only packing a single value at time. Instead, the pack() function in the <<PythonModule struct>> module takes a format string containing several characters, along with the values to be packed:

>>> struct.pack('iii',  127, 1972, 1234567890)
'\177\000\000\000\264\007\000\000\322\002\226I'

Repeated format characters can be written as a single character preceded by an integer repeat count; the previous example could have been written as struct.pack(‘3i’, ...), and would produce identical results.

Different-sized values can be packed using several different format characters, whose output will vary in size. For example, the “b” (byte) character will produce a single byte of output, and therefore is limited to values between -128 and 127. “h” (short) produces 2 bytes, “i” (int) produces 4 bytes, and “l” (long) will be 4 bytes on 32-bit machines, and 8 bytes on most 64-bit machines.

Here’s a table of some of the more commonly used format characters supported by pack() and unpack(). Consult the Library Reference’s section on the <<PythonModule struct>> module for a complete list:

|!Format ~~~~~~|!’‘C Type’‘|!Python ~~~~~~|

|b|**signed char**|integer|

|B|**unsigned char**|integer|

|h|**short**|integer|

|i|**int**|integer|

|l|**long**|integer|

|f|**float**|float|

Because the <<PythonModule struct>> module is often used for packing and unpacking C structs, it obeys the compiler’s alignment rules. This means that padding bytes may be inserted between format characters of different types. For example, the zero byte in the following example is padding:

>>> struct.pack('BH',  255, 65535)
'\377\000\377\377'

Converting from Numbers to Strings

You wish to convert a number to the corresponding string representation. For example, you want to convert a number like 144 to the string ‘144’.

The simplest way is to use the built-in function str(), or the backquote notation `144`. Both solutions will convert the number to a string in the most straightforward way.

V = 187.5
S = str(V)  # Produces '187.5'

If V contains an integer or long integer, and you want to convert the number to hexadecimal or octal representation, use the built-in functions hex() or oct().

>>> hex(187)
'0xbb'
>>> oct(187)
'0273'

If fancier formatting is required, such as rounding a floating-point number to a given number of decimal places, or padding a number with zeros, use the % operator on strings, which allows more precise control of the output.

>>> "%04d" % (87,)
'0087'
>>> "%.2f" % (187.375,)
'187.38'

(See the Library Reference manual for the complete details of the available format characters.)

There’s no library function to convert a number to its base-2 representation, so here’s a function to do the job.

def atob(number):
   """Returns a string containing the binary representation of a number"""
   if number < 0:
       prefix = "-" ; number = -number
   elif number == 0: return "0"
   else:
       prefix = ""

   # Loop, looking at the lowest bit of the number an
   s = ""
   while number > 0:
       s = chr( 48+ (number  1) ) + s
       number = number >> 1
   return prefix + s

English Ordinals

Here’s a one-liner that will add the English ordinal suffix to a number:

ord_text = lambda n: str(n) + {1: 'st', 2: 'nd', 3: 'rd'}.get(n % (10 < n % 100 < 14 or 10), 'th')

Originally from [[Paul Bissex|http://news.e-scribe.com/418]]

Generating Random Numbers

Problem

You need to generate random numbers for an application, such as generating test data or selecting an item from a list.

Solution

The standard library module <<PythonModule random>> implements a random number generator. Using it is simple:

import random

# Generate a random number between 0 and 1
randval = random.random()

# Generate a random integer between 45 and 55
randval = random.randint(45, 55)

# Choose a random value from a list
randname = random.choice( ["Glenna", "Jody", "Natalie"] )

Discussion

random.random() returns a random floating point number in the range [0, 1), generated using a Wichmann-Hill <<Wikipedia ‘random number’ Random_number>> generator. There are also other specialized generators in this module, built on top of the random() function:

  • randint(a, b) chooses an integer in the range [a, b]
  • choice(S) chooses a random item from the given sequence S
  • uniform(a, b) chooses a floating point number in the range [a, b]

To specify the random number generator’s initial setting, use random.seed(x, y, z), which sets the seed from three integers in the range [1, 256]. There’s also a random class, which you can instantiate to create independent multiple random number generators.

The <<PythonModule random>> module contains functions that approximate various standard distributions, such as a normal or Gaussian distribution, lognormal, gamma and beta distributions, and a few others. These functions are specialized enough to make me refer you to the Python Library Reference for the details.

Note that the rand module, which is occasionally used in some examples and demo programs, is now considered obsolete. Use <<PythonModule random>> instead.

Generating a Random Permutation

A related problem to [[generating random numbers|Generating Random Numbers]] is generating a random permutation of numbers between 1 and N, with no repeats. For example, you might want to rearrange a list into a random order.

The solution is to generate a list containing the numbers from 1 to N, and use the random.choice() function to pick a random element. Remove the chosen element, and then repeat until the list is empty.

numbers = range(1, N+1)
while numbers:
   j = random.choice(numbers)
   numbers.remove(j)
   print j

Mathematical Functions

Problem

You want to perform a calculation that requires operations beyond the basic ones of addition, subtraction, multiplication, division, and exponentiation. For example, you need to evaluate a sine or cosine.

Solution

Import the <<PythonModule math>> module, and use the functions that it provides.

import math

angle = math.pi / 6
x = math.cos( angle )
y = math.sin( angle )

If you want to get results that are complex numbers, use the <<PythonModule cmath>> module.

import cmath
result = cmath.sin( 1+3j )

Discussion

Mathematical functions such as sine and cosine are contained in the <<PythonModule math>> module. The functions are identical to those defined by the C standard, since they’re simply Python wrappers on top of those functions. The <<PythonModule math>> module also defines two constants: pi**and **e.

The functions in <<PythonModule math>> always return floating point numbers, whether the input was an integer or a float. If a result would be a complex number (math.sqrt(-1), the square root of -1, is the common example), this is considered an error and triggers an exception. To get complex numbers as answers, you need to use the <<PythonModule cmath>> module, which is similar (though not identical) to the <<PythonModule math>> module, and can handle complex parameters and results:

>>> math.sqrt(-1)
Traceback (innermost last):
 File "<stdin>", line 1, in ?
OverflowError: math range error
>>> cmath.sqrt(-1)
1j

Here’s a list of the functions contained in the <<PythonModule math>> module. The <<PythonModule cmath>> module defines analogous functions that operate on complex numbers.

|!Name ~~~~|!Purpose ~~~~~~~|

|**acos(x)**|Arc cosine of x|

|**asin(x)**|Arc sine of x|

|**atan(x)**|Arc tangent of x|

|**atan2(x,y)**|Arc tangent of **x/y**|

|**ceil(x)**|Ceiling of x; the largest integer equal to or greater than x|

|**cos(x)**|Cosine of x|

|**cosh(x)**|Hyperbolic cosine of x|

|**exp(x)**|e raised to the power of x|

|**fabs(x)**|Absolute value of x|

|**floor(x)**|Floor of x; the largest integer equal to or less than x|

|**fmod(x)**|x modulo y|

|**frexp(x)**|The matissa and exponent for x.|

|**hypot(x, y)**|Euclidean distance, **sqrt(x*x + y*y)**|

|**ldexp(x, i)**|**x * (2**i)**|

|**log(x)**|Natural logarithm of x|

|**log10(x)**|Base 10 logarithm of x|

|**modf(x)**|Return the fractional and integer parts of x|

|**pow(x, y)**|x raised to the power of y|

|**sin(x)**|Sine of x|

|**sinh(x)**|Hyperbolic sine of x|

|**sqrt(x)**|Square root of x|

|**tan(x)**|Tangent of x| |**tanh(x)**|Hyperbolic tangent of x|