Python Concepts/Numbers

=Objective=


 * Learn about Python integers.
 * Learn about non-decimal integers.
 * Learn about Python floats.
 * Learn about precision of floats.
 * Learn about Boolean algebra. (Booleans are a subclass of integers. )
 * Learn about complex numbers in Python.
 * Learn how to convert numbers into different basic data types.

=Lesson=

Data Types
This is the first of several lessons on the data types used by Python. Computer programs can process instructions that work with many different kinds of data, and the instructions need to be very precise. If you add a word to this sentence, 'add' means something very different from when you add 2 and 3. A computer language has to have a set of rules defining what operations can be applied to different kinds of data, and for this to work, there also has to be a set of rules defining exactly what data can be used with each operation. For example, if you want to calculate grossProfit = salesIncome - costs, a program has to know that these quantities are variables containing numbers rather than just strings of letters. They must have a numerical data type rather than string data type.

If you are not clear about the meaning in computer science of variables and of data types, it may help to brush up on the lesson Introduction_to_Programming/Variables.

class type(object)
With one argument, return the type of an object.

isinstance(object, classinfo)
Return true if the object argument is an instance of the classinfo argument. classinfo can be a tuple. isinstance arg 2 must be a type or tuple of types.

=Python Integers=

Introduction to integers
Python has several data types to represent numbers. This lesson introduces two: integers, and floating point numbers, or 'floats'. We'll discuss floats later in the lesson. An integer, commonly abbreviated to int, is a whole number (positive, negative, or zero). So,  ,  ,  , and   are integers. ,,  , and even   are not integers, they are floats in Python. To test if this is true, we can use the  built-in function to test if a number is or isn't an integer.

A decimal integer contains one or more digits "0" ... "9". Underscores may be used to improve readability. With one exception described in floats below, leading zeros in a non-zero decimal number are not allowed.

We can perform simple mathematical operations with integers, like addition, subtraction , multiplication , and division. Here are some examples using simple math.

You should have noticed three things in the above example. First, all mathematical operations follow an order of operations, called precedence; multiplication and division are done first, then addition and subtraction are performed, hence why  didn't result in. Secondly, when you divide, a float is always the result. Lastly, by putting a minus sign in front of a number, it will become a negative number.

You can do more mathematical operations than the previously demonstrated ones. We can perform a floor division by using two forward slashes to divide and have the result as an integer.

Now, that may save us trouble, but what if we want to get just the remainder of a division? We can perform a modulo operation to get the remainder. To perform a modulo, use a percent sign.

The  built-in function returns both quotient and remainder:

You can also find the power of a number by using two asterisk symbols. The operator of exponentiation  has higher precedence than or  or unary

If unsure of precedence, you can always use parentheses to force the desired result:

There is no limit for the length of integer literals apart from what can be stored in available memory.

Non-decimal Integers
Almost everyone is familiar with ten based numbers. While base 10 is useful for everyday tasks, it isn't ideal for use in the computer world. Three other numeral systems are commonly used in computer science; binary, octal, and hexadecimal. We'll lightly cover Python's use of these in this section. The binary system is essential as all information is represented in binary form in computer hardware. Octal and hexadecimal are convenient for condensing binary numbers to a form that is more easily read by humans, while (unlike decimal) being simple to translate to or from binary. If you have difficulty with this part of the lesson, it may help to brush up on the lesson Numeral_systems in the course Introduction_to_Computers.

Most people have heard of binary and it is often associated with computers. Actually, modern binary made its way into the world far before electricity was widely in use. The binary system is 2 based, which means that only two numbers are used. Of course, these numbers are 0 and 1. So $$1+1=10_2,$$ unlike the decimal's $$1+1=2_{10}.$$ To use binary numbers in python, prepend  or   to the number.

The value returned by  is a string. The underscore may be used to make numbers more readable.

The octal numeral system is something that really isn't used anymore, since it was superseded by hexadecimal. The octal system made sense decades ago when hardware was expensive, because the 8 based system can fit into three bits perfectly. Though this scheme fits into bits, it does not fit into a standard byte, which is 8 bits. Since the octal numeral system is 8 based, you can only use numbers "0"..."7". To use octal numbers in python, prepend  or   to the beginning of the number. You may find it easier to use a lowercase o instead of an uppercase O, since it could be confused as a zero.

The hexadecimal numeral system is widely used when working with computers, because one hexadecimal digit can fit into a nibble (4 bits). Since a standard byte is 8 bits, two nibbles could perfectly fit into a byte, hence why the octal system is rather obsolete. Hexadecimal has 16 digits, which consist of "0"..."9" and "A"..."F" or "a"..."f". "Letters as numbers?", you may say. Indeed, it may be tricky working with letters as numbers, but once you get comfortable with them, it will be easy to use. To use hexadecimal numbers in python, prepend  or   to the beginning of the number. I suggest using a lowercase x, since it is easier to distinguish from the numbers and uppercase letters.

This topic has been lightly brushed up on and will probably not be used until later in advanced lessons. If you feel a need to learn this, or you want to be proficient at it, the course Introduction to Computers has a lesson called Numeral systems that deals with these numeral systems with a little more in depth teaching.

Bitwise Operators
All integers may be tested or modified by the Bitwise Operators:  (and),   (or), (exclusive or),  (shift left),   (shift right) and (invert). However it makes good sense to confine our description of these operators to non-decimal integers, particularly binary and hexadecimal.

These operators are called 'bitwise' because they operate on individual bits within the integer.

1. The  operator produces a true output when both corresponding bits are true:

In the first example both input operands have the marked bits set and the result is

2. The  operator produces a true output when at least one of both corresponding bits is true:

In the first example both input operands have the marked bits set in at least one of the operands and the result is

3. The  operator produces a true output when exactly one of both corresponding bits is true:

In the first example both input operands have the marked bits set in exactly one of the operands and the result is

4. The  operator shifts the operand left by the number of bits specified:

In the first example the output is the input shifted left 2 bits: The ouput is the input with two 0's at the right hand end.

5. The  operator shifts the operand right by the number of bits specified:

In the first example the output is the input shifted right 2 bits: The rightmost two bits of the input are lost forever. If you wish to preserve the 2 rightmost bits of the input, before shifting execute:

The bitwise operators above perform as expected on all integers of (almost) unlimited length:

6. The behavior of the invert (~) operator shows that negative numbers are treated as their 2’s complement value:

For a true 1's complement bitwise invert here is one way to do it:

And another way to do it:

When you execute the above code, you see the following results: The Decimal.logical_invert performs a 1's complement inversion.

=Python Floats=

Introduction to floats
Although integers are great for many situations, they have a serious limitation, integers are whole numbers. This means that they do not include all real numbers. A real number is a value that represents a quantity along a continuous line, which means that it can have fractions in decimal forms. ,, and   are all real numbers. In computer science, real numbers are represented as floats. To test if a number is float, we can use the  built-in function.

As a general rule of thumb, floats have a decimal point and integers do not have a decimal point. So even though  and   are the same number,   is an integer while   is a float.

The basic arithmetic operations used for integers will also work for floats. (Bitwise operators will not work with floats.)

Some technical information about 'floats.'
A floating point literal can be either pointfloat or exponentfloat.

A pointfloat contains a decimal point  and at least one digit   for example:

An exponentfloat contains an exponent which

means that  or   is required.

means that  or   is optional.

means decimal integer.

These are examples of exponents:

The exponent is interpreted as follows:

$$.5e2 = .5(10^2) = 50.0$$ ; $$-3E1 = -3.0(10^1) = -30.0$$ ; $$.003e-5 = .003(10^{-5}) = 3e-08$$ ; $$3e0 = 3.0(10^{0}) = 3.0$$ ; $$0090.5e-02 = 90.5(10^{-2}) = 0.905$$ ; $$0E0 = 0.0(10^0) = 0.0$$

An exponent float can be either:

decinteger exponent, for example:  or

pointfloat exponent, for example:

The separate parts of a floating point number are: $$\underbrace{12345}_\text{significand} \times \underbrace{10}_\text{base}\!\!\!\!\!\!^{\overbrace{-4}^\text{exponent}}.$$

The  may be called   or   The   may be called The  may be called   or

Within the floating point literal white space is not permitted. An underscore  may be used to improve readability. Integer and exponent parts are always interpreted using radix Within the context of floating point literals, a "decinteger" may begin with a Numeric literals do not include a sign; a phrase like   is actually an expression composed of the unary operator  and the literal

sys.float_info
Object  contains information about floats:

Information about some of the above values follows:

sys.float_info.dig
As shown above some (but not all) decimal numbers of 16 digits can be accurately represented as a float. Hence 15 as the limit in.

The Precision of Floats
Before you start calculating with floats you should understand that the precision of floats has limits, due to Python and the architecture of a computer. Some examples of errors due to finite precision are displayed below.

In the first example,, although Python comes to the conclusion that the real answer is. The fact behind this reasoning is based on how the computer stores memory, so the difference lost a little of its precision. As the minuend increases in size, so does its precision. and.

In the second example,  where   means ten to the power of negative five. The answer could also be  depending on how the quotient is rounded, how long the quotient can be stored on the computer, and the most significant number on the right hand side.

In the third example, the sum of the addends  although we know that it really is. The reason the second addend is left out is because of its insignificance. Although this might not matter for every day situations, it may be important for such uses as rocket science and possibly calculus.

The fourth example gives the correct result if rewritten:

When working with Python floats, we need to be aware that there will probably be a margin of error.

Decimal fixed point and floating point arithmetic for extreme precision
The Python "Decimal" module provides support for fast correctly-rounded decimal floating point arithmetic. The module offers several advantages over the float datatype, including:


 * Decimal numbers can be represented exactly.
 * The decimal module has a user alterable precision (defaulting to 28 places) which can be as large as needed for a given problem.

The usual start to using decimals is importing the module, viewing the current context with getcontext and, if necessary, setting new values for precision, rounding, or enabled traps:

We are now ready to use the decimal module.

$$(\sqrt{2})^2$$ $$(2.12345678^{(\frac{1}{2.345})})^{2.345}$$

Some mathematical functions are also available to Decimal:

Lack of precision in the real world
(included for philosophical interest)

Simple tests indicate that the error inherent in floating point operations is about $$\frac{1}{10^{16}}.$$

This raises the question "How much precision do we need?"

For decades high school students calculated sines and cosines to 4 decimal places by referring to printed look-up tables. Before computers engineers used slide rules to make calculations accurate to about $$\frac{1}{1000}$$ for most calculations, and the Brooklyn Bridge is still in regular use.

With accuracy of $$\frac{1}{10^{16}}$$ engineers can send a rocket to Pluto and miss by 1cm.

If your calculations produce a result of $$1.0(10^{-14})$$ and you were expecting $$0,$$ will you be satisfied with your work? If your calculations were in meters, probably yes. If your calculations were in nanometers ($$10^{-9}$$ of a meter), probably no.

Knowing that lack of precision is inherent in floating point operations, you may have to include possibly substantial amounts of code to make allowances for it.

Extreme Precision
(included for historical interest)

If you must have a result correct to 50 places of decimals, Python's integer math comes to the rescue. Suppose your calculation is:

$$123456.789 / 4567.87654 $$ $$= \frac{123456.789 }{4567.87654 } $$ $$= \frac{123456.78900 }{4567.87654 }$$ $$= \frac{12345678900 }{456787654 }.$$

For 50 significant digits after the decimal point your calculation becomes:

$$123456.789 / 4567.87654 $$ $$= \frac{12345678900(10^{51}) }{456787654(10^{51}) }$$ $$= \frac{12345678900(10^{51}) }{456787654 }/10^{51}.$$

The correct result $$= 27027172892899596625262555804540198890751981663672548(10^{-51}),$$ but note:

Put the decimal point in the correct position within a string to preserve precision:

Format the result:

Both strings and

are

acceptable as input to Python's Decimal module.

Lack of precision and what to do about it
Lack of precision in floating point operations quickly becomes apparent:

count= 1, sum = 1e-10 count= 2, sum = 2e-10 count= 3, sum = 3e-10 count= 4, sum = 4e-10 count= 5, sum = 5e-10 count= 6, sum = 6e-10 count= 7, sum = 7e-10 count= 8, sum = 7.999999999999999e-10

The problem seems to be that floating point numbers are contained in 53 bits, limiting the number of significant digits in the decimal number displayed to 15 or 16. But this is not really the problem. If the standard limits the number of significant digits displayed to 15 or 16, so be it. The real problem is that underlying calculations are also performed in 53 bits.

Precision greater than standard
Rewrite the above code so that the value  has precision greater than standard.

$$ = \frac{1}{10^{10}} = \frac{x}{16^{26}};\ x = \frac{16^{26}}{10^{10}}$$

Exact value of increment:

count = 1, sum = 0x6df37f675ef6eadf5bp-104, sum as float = 1e-10 count = 2, sum = 0xdbe6fecebdedd5beb6p-104, sum as float = 2e-10 count = 3, sum = 0x149da7e361ce4c09e11p-104, sum as float = 3e-10 ........................... count = 997, sum = 0x1ac354f2d94d7a0b7dd67p-104, sum as float = 9.97e-08 count = 998, sum = 0x1aca342acfc3697a2bcc2p-104, sum as float = 9.98e-08 count = 999, sum = 0x1ad11362c63958e8d9c1dp-104, sum as float = 9.99e-08 Consider the last line above:.

The most accurate hex representation of value  with this precision is in fact   different from the above value by. If counting continues, drift increases but, as a fraction of sum, it remains fairly constant, apparently enabling accurate counting up to and including the theoretical limit of floats (15 decimal digits.)

drift vvv count = 999, sum = 0x1ad11362c63958e8d9c1dp-104, sum as float = 9.99e-08 0x1AD11362C63958E8D9B0Ap-104 most accurate hex representation of sum as float ^^^^^^^^^^^^^^^^^^                    18 hex digits = 69 bits

drift vvvvv count = 99999, sum = 0xa7c53e539be0252c255b85p-104, sum as float = 9.9999e-06 0xA7C53E539BE0252C24F026p-104 most accurate hex representation of sum as float ^^^^^^^^^^^^^^^^^                      17 hex digits = 68 bits

drift vvvvvvvv count = 9999999999, sum = 0xffffffff920c8098a1aceb2ca5p-104, sum as float = 0.9999999999 0xFFFFFFFF920C8098A1091520A5p-104 most accurate hex representation of sum as float ^^^^^^^^^^^^^^^^^^                           18 hex digits = 72 bits

drift 15 decimal digits                          vvvvvvvvvvvvv count = 999999999999999, sum = 0x1869fffffffff920c81929f8524a0a5p-104, sum as float = 99999.9999999999 0x1869FFFFFFFFF920C8098A1091520A5p-104 most accurate hex representation of sum as float ^^^^^^^^^^^^^^^^^^                                18 hex digits = 69 bits

Exact value of sum:

While floating point operations implemented in software might not depend on conversion to and from hex strings, the above illustrates the accuracy that could be obtained if floating point software of selectable precision were to replace now antiquated floating point hardware.

Python's decimal module allows floating point calculations of (almost) infinite precision, but importing a special module to perform a calculation like $$1.13 - 1.1$$ seems onerous.

In a programming language as magnificent as Python, the above result is intolerable.

Python's Decimal module
With a few simple changes the above counting loop takes full advantage of Python's Decimal module, and possible loss of precision becomes irrelevant. count = 1, sum = 1E-10 count = 2, sum = 2E-10 count = 3, sum = 3E-10 ................. count = 997, sum = 9.97E-8 count = 998, sum = 9.98E-8 count = 999, sum = 9.99E-8 A float is displayed with 'e', a Decimal object with 'E'.

Using formatted string
count= 1, sum = 1e-10 count= 2, sum = 2e-10 count= 3, sum = 3e-10 ................. count= 997, sum = 9.97e-08 count= 998, sum = 9.98e-08 count= 999, sum = 9.99e-08

Using Decimal precision
Python's floating point standard states that the best accuracy to be expected is 15 significant decimal digits.

count =  1    d1 = sum =                 1E-10    d1 =                1E-10    sum = 1e-10 count =  2    d1 = sum =                 2E-10    d1 =                2E-10    sum = 2e-10 count =  3    d1 = sum =                 3E-10    d1 =                3E-10    sum = 3e-10 count =  4    d1 = sum =                 4E-10    d1 =                4E-10    sum = 4e-10 count =  5    d1 = sum =                 5E-10    d1 =                5E-10    sum = 5e-10 count =  6    d1 = sum =                 6E-10    d1 =                6E-10    sum = 6e-10 count =  7    d1 = sum =                 7E-10    d1 =                7E-10    sum = 7e-10 count =  8    d1 = sum = 7.999999999999999E-10    d1 = 8.00000000000000E-10    sum = 8e-10 count =  9    d1 = sum =                 9E-10    d1 =                9E-10    sum = 9e-10 count = 10    d1 = sum =                  1E-9    d1 =                 1E-9    sum = 1e-09 count = 11    d1 = sum = 1.1000000000000001E-9    d1 =  1.10000000000000E-9    sum = 1.1e-09 count = 12    d1 = sum =                1.2E-9    d1 =               1.2E-9    sum = 1.2e-09 count = 13    d1 = sum =                1.3E-9    d1 =               1.3E-9    sum = 1.3e-09 count = 14    d1 = sum = 1.4000000000000001E-9    d1 =  1.40000000000000E-9    sum = 1.4e-09 count = 15    d1 = sum =                1.5E-9    d1 =               1.5E-9    sum = 1.5e-09 count = 16    d1 = sum =                1.6E-9    d1 =               1.6E-9    sum = 1.6e-09 .............................. count = 296   d1 = sum =               2.96E-8    d1 =              2.96E-8    sum = 2.96e-08 count = 297   d1 = sum =               2.97E-8    d1 =              2.97E-8    sum = 2.97e-08 count = 298   d1 = sum = 2.9800000000000002E-8    d1 =  2.98000000000000E-8    sum = 2.98e-08 count = 299   d1 = sum = 2.9899999999999996E-8    d1 =  2.99000000000000E-8    sum = 2.99e-08 count = 300   d1 = sum = 3.0000000000000004E-8    d1 =  3.00000000000000E-8    sum = 3e-08 count = 301   d1 = sum =               3.01E-8    d1 =              3.01E-8    sum = 3.01e-08 count = 302   d1 = sum =               3.02E-8    d1 =              3.02E-8    sum = 3.02e-08 .............................. count = 997   d1 = sum =               9.97E-8    d1 =              9.97E-8    sum = 9.97e-08 count = 998   d1 = sum =               9.98E-8    d1 =              9.98E-8    sum = 9.98e-08 count = 999   d1 = sum =  9.989999999999999E-8    d1 =  9.99000000000000E-8    sum = 9.99e-08

The last line:

count = 999$$\ \ \ \ $$ d1 = sum = $$\ \ \underbrace{9.9899\_9999\_9999\_999}_\text{16 significant digits}$$E-8$$\ \ \ \ $$ d1 =      $$\ \ \underbrace{9.9900\_0000\_0000\_00}_\text{15 significant digits}$$E-8$$\ \ \ \ $$ sum = 9.99e-08

The value  means that this is the most accurate value for   that can fit in 15 significant digits.

=The Boolean=

In Python and most languages, a Boolean can be either  or. A Boolean is a special data type and is a subclass of int. Since a Boolean has two states and only one at a time, a Boolean creates a special relationship between things. We can think of some Boolean values that we deal with in real life, for example: on or off, hot or cold, light or darkness, etc. Although a Boolean can be  or   a Boolean expression can take a statement, like   or , and turn it into a Boolean,   for the former and   for the latter. We can use the  method to check the Boolean value of an object, which will be   for integer zero and for objects (numerical and other data types) that are empty, and   for anything else.

You can also use three operators to alter a Boolean statement :,  ,. You can use an  statement to allow one or more Booleans to be False so long as one is True. An  statement requires all of the Booleans to be True for it be True. The  statement reverses a Boolean so   is   and   is. Here are some examples:

All of the possible combinations are:

The above negated statements reflect "De Morgan's laws." For example, the statement is equivalent to: $\overline{True and True}$ $$\equiv$$ $\overline{True}$ or $\overline{True}$.

A simple way to choose one of two possible values:
Produce list L2, a copy of L1, except that each value 0 in L1 has been replaced by 0xFF:

Expressions containing multiple booleans
Consider the expression:

Does this mean

Does it mean

It might be tempting to say that there is no difference, but look closely:

for A = False, B = True, C = True (A and B) or C = True A and (B or C) = False

for A = False, B = False, C = True (A and B) or C = True A and (B or C) = False

Add another boolean to the expression:

and the number of different possibilities is at least 96.

You can see that the complexity of these expressions quickly becomes unmanageable.

The essence of this section: Keep your expressions simple and use parentheses as necessary to ensure that your code is interpreted exactly as you expect.

=Complex Numbers=

A complex number is represented as  where   and b are real numbers, like 7 or 12, and   is an imaginary number, where. In the computer field, and in the world of Python,  is denoted as   for technical reasons, so we use. It should also be noted that  and   are both treated as floats. This subject will be briefly covered until later lessons. Note also that j cannot be used on its own without b. If you try to use j on its own, Python will look for a variable  and use the value of that variable, or report an error if the variable is not known or a wrong type. So the imaginary number i or j must always be written as 1j. The last result illustrates that even when the variable j has a numerical value, 1j (where, as above, can be any number) is always interpreted as the imaginary number j, not the variable j.

The usual mathematical operations can be performed on complex numbers: Look closely at the last example. It does not produce an error, but is it what you want?

You can extract the real number and the imaginary number by using  and   respectively.

Introduction


A Python complex number  is stored internally using rectangular or Cartesian coordinates. It is completely determined by its real part  and its imaginary part.

See Figure 1. In Cartesian Geometry of 2 dimensions the real part of complex number  is parallel to the $$X$$ axis and the imaginary part is parallel to the $$Y$$ axis. The  of  is the line from origin to   with length.

In scientific notation the number  is written as $$a + bi$$ where $$i = \sqrt{-1}.$$ Within Python is written as

Note: Because the expression 'bj' could be the name of a variable, and to avoid confusion, it might be better to express a complex number within Python as.

The values  are the rectangular coordinates of complex number.

The absolute value of a complex number is the length of the modulus:

$$r = \sqrt{Z.real^2 + Z.imag^2}$$

Some useful constants:

Addition of complex numbers
To add two complex numbers in rectangular format, simply add the real parts, then the imaginary parts:

Polar coordinates
Polar coordinates provide an alternative way to represent a complex number. In polar coordinates, a complex number is defined by the  and the. The modulus  is   as above, while the phase   is the counterclockwise angle, measured in radians, from the positive x-axis to the line segment that joins the origin to.

$$\tan \phi = \frac{Z.imag}{Z.real}.$$

Class method  returns the phase:

From figure 1:

$$\cos \phi = \frac{Z.real}{r};\ Z.real = r \cos \phi.$$

$$\sin \phi = \frac{Z.imag}{r};\ Z.imag = r \sin \phi.$$

If polar coordinates are known:

$$Z = r \cos \phi + 1j * r \sin \phi = r (\cos \phi + 1j * \sin \phi).$$

De Moivre's formula
The format containing polar coordinates is useful because:

$$Z^n = r^n(\cos(n\phi) + i\sin(n\phi))$$

Z^2
$$Z^2 = r^2(\cos(2\phi) + i\sin(2\phi))$$

Proof
$$Z = r(\cos\phi + i\sin\phi)$$

$$Z^2 = (r(\cos\phi + i\sin\phi))^2$$

$$Z^2 = r^2(\cos\phi + i\sin\phi)^2$$

$$Z^2 = r^2(\cos^2\phi + 2i\sin\phi\cos\phi - \sin^2\phi)$$

$$Z^2 = r^2(\cos^2\phi - \sin^2\phi + 2i\sin\phi\cos\phi)$$

$$Z^2 = r^2(\cos(2\phi) + i\sin(2\phi))$$

Z and Z^2 on polar diagram


In Figure 2 $$Z_1 = 3 + 1j*\frac{5}{4}$$.

$$Z_2 = -3 + 1j*(-\frac{5}{4})$$ $$= -3 - 1j*\frac{5}{4}$$ $$= -(3 + 1j*\frac{5}{4}) = -Z_1.$$

$$r_1$$ = length $$OZ_1$$ = abs$$(Z_1) = r_2$$ = length $$OZ_2$$ = abs$$(Z_2) = \frac{13}{4}.$$

$$$$$$$$$$$$$$$$

Angle $$\phi$$ is the phase of $$Z_1.\ \cos \phi = \frac{12}{13}.\ \sin \phi = \frac{5}{13}$$.

$$Z_1 = r_1*(\cos \phi + 1j* \sin \phi)$$ $$= \frac{13}{4}*(\frac{12}{13} + 1j*\frac{5}{13})$$ $$= 3 + 1j*\frac{5}{4}.$$

$$r$$ = length $$OZ$$ = abs$$(Z) = r_1^2 = \frac{169}{16}.$$

Phase of $$Z = 2\phi.$$ Therefore: $$Z = Z_1^2 = Z_2^2.$$

$$\sin 2\phi = 2\sin\phi\cos\phi$$ $$= 2(\frac{5}{13})(\frac{12}{13})$$ $$= \frac{120}{169}.$$

$$\cos 2\phi = \cos^2\phi - \sin^2\phi$$ $$= (\frac{12}{13})(\frac{12}{13}) - (\frac{5}{13})(\frac{5}{13})$$ $$= \frac{144-25}{169}$$ $$= \frac{119}{169}.$$

$$Z = r*(\cos 2\phi + 1j*\sin 2\phi)$$ $$= \frac{169}{16}(\frac{119}{169} + 1j*\frac{120}{169})$$ $$= \frac{119}{16} + 1j*\frac{120}{16}$$ $$= 7\frac{7}{16} + 1j*7\frac{1}{2}.$$

\sqrt{Z}
---

$$\sqrt{Z} = \sqrt{r}(\cos(\phi/2) + i\sin(\phi/2))$$

\sqrt{1}
$$\cos(0) + 1j*\sin(0) = 1 + 1j*0 = 1$$

$$\sqrt{1} = \sqrt{\cos(0) + 1j*\sin(0)}$$ $$= \cos(0/2) + 1j*\sin(0/2)$$ $$= \cos(0) + 1j*\sin(0) = 1$$

Trigonometric functions are cyclical:

$$\cos(360) + 1j*\sin(360) = 1 + 1j*0 = 1$$

$$\sqrt{1} = \sqrt{\cos(360) + 1j*\sin(360)}$$ $$= \cos(360/2) + 1j*\sin(360/2)$$ $$= \cos(180) + 1j*\sin(180) = -1 + 1j*0 = -1$$

The two square roots of  are   and

\sqrt{-1}
$$\cos(180) + 1j*\sin(180) = -1 + 1j*0 = -1$$

$$\sqrt{-1} = \sqrt{\cos(180) + 1j*\sin(180)}$$ $$= \cos(180/2) + 1j*\sin(180/2)$$ $$= \cos(90) + 1j*\sin(90) = 0 + 1j*1 = 1j$$

Trigonometric functions are cyclical:

$$\cos(180+360) + 1j*\sin(180+360) = -1 + 1j*0 = -1$$

$$\sqrt{-1} = \sqrt{\cos(180+360) + 1j*\sin(180+360)}$$ $$= \cos(90+180) + 1j*\sin(90+180)$$ $$= \cos(270) + 1j*\sin(270) = 0 + 1j*(-1) = -1j$$

The two square roots of  are   and

Cube roots of 1 simplified
$$\cos(0) + 1j*\sin(0) = 1 + 1j*0 = 1$$

$$\sqrt[3]{1} = (\cos(0) + 1j*\sin(0))^{(1/3)}$$ $$= \cos(0/3) + 1j*\sin(0/3)$$ $$= \cos(0) + 1j*\sin(0) = 1$$

Trigonometric functions are cyclical:

$$\cos(360) + 1j*\sin(360) = 1 + 1j*0 = 1$$

$$\sqrt[3]{1} = (\cos(360) + 1j*\sin(360))^{(1/3)}$$ $$= \cos(360/3) + 1j*\sin(360/3)$$ $$= \cos(120) + 1j*\sin(120) = -\cos(60) + 1j*\sin(60) $$ $$= -\frac{1}{2} + 1j\frac{\sqrt{3}}{2} = \frac{-1 + 1j*\sqrt{3}}{2}$$

Proof: $$r_2 = -1(\cos(60) - 1J*\sin(60)) = -1(\cos(-60) + 1J*\sin(-60)).$$ $$r_2^3 = (-1)^3(\cos(-180) + 1J*\sin(-180)) = -1(-1 + 1J*0) = 1.$$

$$\cos(720) + 1j*\sin(720) = 1 + 1j*0 = 1$$

$$\sqrt[3]{1} = (\cos(720) + 1j*\sin(720))^{(1/3)}$$ $$= \cos(720/3) + 1j*\sin(720/3)$$ $$= \cos(240) + 1j*\sin(240) = -\cos(60) - 1j*\sin(60) $$ $$= -\frac{1}{2} - 1j\frac{\sqrt{3}}{2} = \frac{-1 - 1j*\sqrt{3}}{2}$$

Proof: $$r_3 = -1(\cos(60) + 1J*\sin(60))$$. $$r_3^3 = (-1)^3(\cos(180) + 1J*\sin(180)) = -1(-1 + 1J*0) = 1.$$

The three cube roots of 1 are : $$1, -\cos 60^\circ \pm 1j*\sin 60^\circ$$ or $$1,\ \frac{-1 + 1j*\sqrt{3}}{2},\ \frac{-1 - 1j*\sqrt{3}}{2}.$$

Multiplication of complex numbers
To multiply two complex numbers in polar format, multiply the moduli and add the phases.

Proof
$$(\cos A + 1j*\sin A)*(\cos B + 1j*\sin B)$$ $$= \cos A \cos B + 1j*\cos A \sin B + 1j*\sin A \cos B + j^2\sin A\sin B$$ $$= \cos A \cos B - \sin A\sin B + 1j*(\cos A \sin B + \sin A \cos B) $$ $$= \cos(A + B) + 1j*\sin(A + B)$$

cmath.isclose(a, b, *, rel_tol=1e-09, abs_tol=0.0)
Return True if the values a and b are close to each other and False otherwise.

Whether or not two values are considered close is determined according to given absolute and relative tolerances.

The following python code implements this functionality with a list or tuple of numbers as input.

The above test for "approximately equal" is:

This test works for floating point numbers, complex numbers or a mixture of both.

It also ensures that 2 not-equal complex numbers of same absolute value ( for example) fail the test.

With this algorithm, 2 small numbers ( for example) both pass the test for "close to 0," but fail the test for "approximately equal."

cmath.sqrt(x)
Return the square root of

cmath.exp(x)
Return the exponential value.

Euler's formula: $$e^{i \theta} = \cos\theta + 1j*\sin\theta$$

When $$\theta$$ has the value $$\frac{\pi}{3}$$ or $$60$$ degrees:

The case when $$\theta = \pi$$:

The combination of value  and expression   is equivalent to Euler's famous Identity: $$e^{i \pi} = -1$$

When is complex:
According to the rules of exponents, the expression  is equivalent to:

$$e^{(a+bj)} = e^ae^{bj} = e^a(\cos b + 1j*\sin b)$$

$$e^{(1+1j*\pi)} = e^1e^{1j*\pi} = e(-1)$$

=Number Conversions=

Introduction
Since integers and floats can't be mixed together in some situations, you'll need to be able to convert them from one type to another. Luckily, it's very easy to perform a conversion. To convert a data type to an integer, use the  function.

You can even convert strings, which you'll learn about later.

To convert a data type to a float, use the  function. Like the integer, you can convert strings to floats.

You can also use the  function to convert a data type to a Boolean.

Converting a data type to a complex is a little more tricky, but still easy. All you need to do is use the function  which takes two parameters, one of which is optional. The first parameter is the real number, which is required, and the second parameter is the imaginary number, which is optional.

Converting integers, decimal to non-decimal
This conversion is from int to str representing int:

Converting integers, non-decimal to decimal
This conversion is from str representing int to int:

Converting to
Method  returns a bytes object representing an integer where: length (in bytes) must be sufficient to contain int, at least (int.bit_length + 7) // 8 byteorder can be 'big', 'little' or sys.byteorder, signed must be True if int is negative. For example: The bytes object  can represent 0xe205 or -7675 depending on whether it's interpreted as signed or unsigned.

To preserve the original int, let  if necessary and use signed=True.

Converting to
A bytes object is an immutable sequence with every member $$x$$ an int satisfying 0xFF $$>= x >= 0.$$

The classmethod  may be used to convert from bytes object to int.

The value returned is an int represented by the given bytes object or any sequence convertible to bytes object:

Complete conversion
Complete conversion means conversion from int to bytes to int, or from bytes to int to bytes. When converting int/bytes/int, it is reasonable to expect that the final int should equal the original int. If you keep byteorder consistent and signed=True, you will produce consistent results:

Positive number with msb (most significant bit) clear: Negative number with msb clear: Positive number with msb set: Negative number with msb set:

floats
Two methods support conversion to and from hexadecimal strings. Because Python’s floats are stored internally as binary numbers, converting a float to or from a decimal string usually involves a small rounding error. In contrast, hexadecimal strings allow exact representation and specification of floating-point numbers.

from hex
A hexadecimal float as represented by a hexadecimal string and similar to decimal floats can be int, point float or exponent float.

A point float contains a decimal point and at least one hex digit. It may contain an exponent represented by  and a power of 2.

An exponent float contains at least one hex digit and exponent.

Class method  returns the float represented by hexadecimal string. The string  may have leading and trailing whitespace.

point float
Consider.

f1 = $$(3 + \frac{0xA}{16} + \frac{0x7}{16^2} + \frac{0xD}{16^3} + \frac{0x4}{16^4})$$

To simplify the conversion put the hex string in the format of exponent float without decimal point:

f1 = $$(3 + \frac{0xA}{16} + \frac{0x7}{16^2} + \frac{0xD}{16^3} + \frac{0x4}{16^4})(16^4)(16^{-4})$$

f1 = $$(3(16^4) + \frac{0xA(16^4)}{16} + \frac{0x7(16^4)}{16^2} + \frac{0xD(16^4)}{16^3} + \frac{0x4(16^4)}{16^4})(16^{-4})$$

f1 = $$(0x30000 + 0xA000 + 0x700 + 0xD0 + 0x4)(16^{-4})$$

f1 = $$(0x3A7D4)(16^{-4}) = 0x3A7D4(2^{-16})$$

point float with exponent
Consider.

f1 = $$(3 + \frac{0xA}{16} + \frac{0x7}{16^2} ) * (2^{10})$$

To simplify the conversion put the hex string in the format of exponent float without decimal point:

1/3
Consider

f1 = $$(0 + \frac{5}{16} + \frac{5}{16^2} + \frac{5}{16^3} + ... + \frac{5}{16^{20}})$$

To simplify calculation of f1:

f1 = $$0x \underbrace{55555555555555555555}_\text{20 hex digits} (16^{-20}) = 0x55555555555555555555(2^{-80})$$

Exact value of hex string representing $$\frac{1}{3}$$  $$\frac{0x55555555555555555555}{2^{80}}.$$

More room for error with greater precision
Consider the hex representation of float.

See what happens when there is an error of only 1 in the rightmost hex digit:

With limited precision calculations have to be perfect because there is no room for error. See what happens when there is greater precision:

Less than perfect floating point calculations can be tolerated when there is greater precision in the underlying calculations. If floating point software with greater precision were to be used, reset the underlying hex value when it's obvious that it should reflect the correct value of the displayed float.

to hex
Instance method  returns a representation of a floating-point number as a hexadecimal string.

The significand in standard form: $$0x1 \underbrace{89126e978d4fe}_\text{13 hex digits}$$

Number of bits in significand =  Recall that

In standard form
Conversion to hex string with 13 places of decimals as above:

$$\frac{24567}{1000} = \frac{x}{16^{13}};$$ $$x = \frac{24567(16^{13})}{1000}$$

Truncate and round  so that the result fits in 53 bits:

float.as_integer_ratio
Instance method  returns a pair of integers whose ratio is exactly equal to the hex representation of the original float and with a positive denominator.

$$\frac{a}{b} = \frac{67553994410557}{2251799813685248} = \frac{0x3d70a3d70a3d}{2^{51}}$$ =

Conversion with more precision than standard form
To convert  to hex with greater precision than standard form:

Get the power of 2 in standard form:

Decide what precision you want. For example, with 4 more hex digits.

Get the value of float  as the exact ratio of two integers:

$$\frac{24567}{1000} = \frac{x}{2^{63}};\ x = \frac{24567(2^{63})}{1000}$$

Exact value of

Exact value of  with greater precision (h1):

Compare the differences:

Exact conversion
The only floating point numbers that can be converted exactly to hex are those that, when expressed as a fraction, have a divisor that is an integer power of 2.

To convert  to hex exactly:

$$1+\frac{71}{2^{67}}$$ $$ = 1+\frac{142}{2^{68}}$$ $$ = 1+\frac{0x8E}{16^{17}}$$ $$ = 0x1\_\underbrace{0000\_0000\_0000\_0008\_E}_\text{17 hex digits} (16^{-17})$$ $$ = 0x1.0000000000000008E$$ $$ = 0x10000000000000008E(2^{-68})$$

Floating point calculation of
Difference $$2^{-52}$$ $$(2^{-52})$$

Exact value of v1:

Exact value of v2:

Exact value of difference:

An observation
While the value  does not contain a repeating decimal, it seems that there is a repeating "decimal" in the hex representation. Repeat the sequence in hex and see what happens:

Exact decimal value of :

Should the point in the hex representation be called a "heximal" point?

User-written floating point software for an accurate result
By inspection produce hex values for  and   accurate to 14 hexadecimal places after the hexadecimal point.

Slightly more precision in the underlying calculations produces an accurate difference:

Exact value of

Summary:

This section simulates the floating-point calculation of $$1.13 - 1.1$$ if the value of attribute could be set to $$57$$ by user.

For examples of professionally written code that temporarily increases precision for underlying calculations and then restores precision to display result, see recipes.

=Miscellaneous Topics=

Plus zero and minus zero
The concept of plus and minus zero does not apply to the integers:

Floats retain the distinction:

As do complex numbers:

Examples of plus and minus zero
A small non-zero positive number was displayed as ; a small non-zero negative number was displayed as.

According to values under "Cube roots of 1 simplified," one of the cube roots of unity is $$r_3 = \frac{-1 - 1j*\sqrt{3}}{2}.$$

We expect that $$r_3^3$$ should equal $$1.$$ However:

The best accuracy which we can expect from floats is 15 significant digits:

The respective values  are the most accurate that can be displayed with 15 places of decimals.

a small non-zero negative number was displayed as.

The conversion from string to float preserves the distinction of minus zero, indicating that the original value was, probably, a small, non-zero, negative number.

Precision and formatted decimals
Within this section the expression "decimal precision" means precision as implemented by Python's decimal module.

Precision means the number of digits used to display a value beginning with and containing the first non-zero digit. Some examples using decimal precision:

Note how the following values are rounded. More about rounding in the next section.

Python's string method  can be used to display a value accurate to a given number of decimal positions.

Default rounding provided by python's string method  is same as that for decimal precision:

Rounding of close but inexact values
Even elementary calculations lead to increasing complexity in the practical execution of a task involving numbers.

It is fairly easy to imagine one fifth of one inch shown mathematically as $$\frac{1}{5}$$ inch.

What if you had to cut from a piece of steel rod a smaller piece with an exact length of $$\frac{1}{5}$$ inch?

Most common measuring instruments have lengths expressed in inches and sixteenths of an inch. Then $$\frac{1}{5}$$ inch becomes $$\frac{3.2}{16}$$ inch.

You use a micrometer measuring instrument accurate to $$\frac{1}{1000}$$ inch and $$\frac{200}{1000}$$ inch is $$\frac{1}{5}$$ inch exactly.

What if you had to produce a piece of steel rod with length $$\frac{1}{7}$$ feet exactly?

$$\frac{1}{7}$$ feet = $$\frac{12}{7}$$ inches = $$1.714285714285$$ inches = $$1\frac{11.428571428571}{16}$$ inches.

Both the measuring tape and micrometer seem inadequate for the task. You devise a system dependent on similar triangles and parallel lines. Success. The value $$\frac{1}{7}$$ can be produced geometrically.

What if you had to produce a square with an exact area of $$2$$ square inches? The side of the square would be $$\sqrt{2}$$ inches exactly, but how do you measure $$\sqrt{2}$$ inches exactly? In practical terms your task becomes feasible if some tolerance in the area of the finished product is allowed, for example $$2 \pm 0.0002$$ square inches. Then a "square" with adjacent sides of 1.4142 and 1.4143 inches has an area within the specified tolerance.

DRIP for example
Even simple calculations based on exact decimals quickly lead to impractical numbers. Suppose you have a DRIP (Dividend ReInvestment Plan) with any of the big well-known corporations. Most DRIPs permit you to purchase fractions of a share of stock. Shares of an attractive stock are currently trading for $$\$38$$ and you invest $$\$100$$, buying $$\frac{100}{38}$$ shares of stock.

On your statement you don't see a credit of $$2\frac{24}{38}$$ shares of stock. The custodian of the plan may show your holding accurate to four places of decimals: $$2.6315$$ shares.

The fraction $$\frac{24}{38}$$ is actually $$0.63157894736........$$ but your credit is $$2.6315$$ called 'rounding down.'

The corporation then issues a dividend of $$\$0.37$$ per share when the stock is trading for $$\$37.26$$ per share and you reinvest the dividend. If the custodian reinvests the dividend for you at a $$5\%$$ discount to market price, your credit is $$\frac{0.37 * 2.6315}{37.26 * 0.95} = 0.02750670960.....$$ shares, shown on your statement as $$0.0275$$ shares giving you a total holding of $$2.6315 + 0.0275 = 2.659$$ shares probably shown on your statement as $$2.6590$$ with a current market value of $$\$2.659 * 37.26 = \$99.07434$$ shown on your statement as $$\$99.07$$.

The result of your mathematical calculations will probably be a close approximation of the exact value after allowing for tolerable errors based on precision and rounding of intermediate results.

Default rounding
When you import python's decimal module, values are initialized as the 'default' values.

The default rounding method is called . This means that, if your result is exactly half-way between two limits, the result is rounded to the nearest even number. For simplicity set precision to 4:

Default rounding provided by python's string method .format is same as that for decimal precision:

A disadvantage of this method of rounding is that an examination of the result does not indicate what the original value was:

ROUND_HALF_UP
Rounding mode ROUND_HALF_UP is illustrated as follows:

Same logic for negative numbers:

ROUND_DOWN
The numbers in the example under DRIP above are derived using python's method and rounding set to ROUND_DOWN.

When using method, ensure that   is adequate:

Many comparisons
If your code contains many numerical comparisons, it may be tempting to put: If all values are equal and non-zero, processing the above statement takes time. For greater speed, put $$0$$ and the value most likely to be non-zero at beginning of comparison:

Divide by 2
Division by 2 seems simple enough: Divisions are time consuming. If b is a large Decimal number, the following code is faster: If b is  right shift is faster than multiplication by  Also, right shift preserves precision of  To preserve rightmost bit:

=Assignments=


 * Experiment with the python interpreter using integers, floats, Booleans, and complex numbers, noting errors, for example:


 * Think critically about integers and floats. When should you use integers? When should you use floats?
 * A loss of significance for a float value should be expected when working with long or insignificant numbers. When would this become a problem?
 * Under "Using formatted string" above the test for correct summation is:

This could be written as:

However:

How would you write the line  to ensure an accurate test?


 * Using techniques similar to those contained in section "Cube roots of 1 simplified" calculate all five of the fifth roots of unity.


 * Using the "Proof" under "Multiplication of complex numbers" show that: $$\frac{\cos A + 1j*\sin A}{\cos B + 1j*\sin B} = \cos(A-B) + 1j* \sin (A-B)$$


 * One of the cube roots of unity, $$r_2 = \frac{-1+1j*\sqrt{3}}{2}.$$

For greater precision than is available with floating point arithmetic, use Python's decimal module to calculate $$r_2^3.$$

=Further Reading or Review=


 * Previous Lesson: To Get You Started
 * This Lesson:Numbers
 * Next Lesson: Strings
 * Course Home Page

=References=

Python's built-in functions:

"abs", "bin", "bool", "complex", "divmod", "eval(expression, ....)", "float", "hex", "int", "oct", "pow", "round", "sys.float_info", "sys.int_info"

Python's documentation:

"3.1.1. Numbers", "Numeric Types", "Integer literals", "Floating point literals", "Imaginary literals", "Operator precedence", "Why are floating-point calculations so inaccurate?", "15. Floating Point Arithmetic: Issues and Limitations", "Decimal fixed point and floating point arithmetic", "4.4.2. Additional Methods on Integer Types", "4.4.3. Additional Methods on Float" "cmath.isclose(a, b, ....)"