4. Booleans, Numbers, and Operations#

This notebook introduces three of the simpler data types within Python: Booleans, integers, and floating-point numbers. In addition, this notebook shows various operations to combine different variables and literals to form an expression with integers and floating-point.

Expressions are any combination of one or more literals(constants), variables, functions, and operators.

Throughout this notebook, practice changing the values and re-running the cells to see what happens.

4.1. Booleans#

Boolean is the simplest data type in Python as the only possible values are True and False. However, software code widely uses Boolean values in many different situations. We can create variables to hold one of these values directly. We will also implicitly use this type as the result of conditional expressions to evaluate whether something is True or False. Control (if) and loop (while) statements will use these results to decide if a code block should execute.

Use Python’s built-in function bool() to convert other data types to Boolean. Any non-zero value will be considered True, and any zero / empty value is considered False.

Side Note: While it looks awkward to capitalize Boolean, we capitalize the term to honor George Boole , who invented algebraic logic in the mid-19th century.

The following expressions evaluate to True:

1True
2bool(True)
3bool(100)
4bool(-100)
5bool(10.0)
6bool("George Boole")
True

The following expressions evaluate to False:

1False
2bool(False)
3bool(0)
4bool(0.0)
5bool("")
False

4.2. Integers#

Integers (\( \mathbb{Z} \)) are whole numbers - they do not have any fractional value or contain a decimal point.

Typically, we write these as a sequence of digits (the characters from 0 to 9). We can add underscores (”_”) to improve readability. However, we can not start an integer value with a 0 followed by other digits. 0 by itself is valid.

11892
1892
10
0
11_000_000
1000000
1012    # causes a "SyntaxError"
  Cell In[6], line 1
    012    # causes a "SyntaxError"
    ^
SyntaxError: leading zeros in decimal integer literals are not permitted; use an 0o prefix for octal integers

4.2.1. Compilation Issues#

In the last cell, the Python interpreter raised a “SyntaxError”, a compilation issue while converting the program text into a symbolic representation. (The Python interpreter then executes that representation.) Before, we have also seen runtime errors as our program executes. We can identify those in Python with the presence of a “Traceback” report in the error message that shows the list of function calls that led to the error. We discuss the different error types and how to handle these errors robustly in a later module.

4.2.2. Integer Bases#

Programs generally represent/use integers as base 10 (decimal) numbers. The base is the number of digits that a counting system uses to represent numbers.

Behind the scenes, computers utilize sequences of bits (zeros and ones) to represent values - even for items other than integers. Humans rely upon abstractions to make sense of those sequences - whether a number, text, images, videos, sound, etc. From a computer’s perspective, everything is a number. For example, images are composed of a series of pixels - layed out in a similar manner to a grid. Each point contains three numbers encoding how much color is contained for the red, green, and blue primary colors. RGB Color Model

Besides decimal, programmers often use three other base representations in code for integers: binary, octal, and hexadecimal.

For Python, we can express literal integers in these three bases in addition to decimal by using specific prefixes:

  • 0b or 0B for binary (base 2). Digits: 0, 1

  • 0o or 0O for octal (base 8). Digits: 0,1,2,3,4,5,6,7

  • 0x or 0X for hexadecimal (base 16). Often this is shortened to “hex”. Digits: 0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f

These prefixes are why we cannot start integer values with 0 and then some other series of digits. While translating program text to the symbolic representation, a tokenizer “chunks” up terms of the program text. The Python tokenizer can correctly determine the chunks for 0 and 0xFF but not for 01.

In the next cell, we show the sequence of 10 using four different bases.

1print(10)
2print(0b10)
3print(0o10)
4print(0x10)
10
2
8
16

Now the value of 42 represented in four different bases

1print(42)
2print(0b101010)
3print(0o52)
4print(0x2A)
42
42
42
42

Hexadecimal characters cab be both lower and upper case.

We can convert integer values to the other bases with bin(), oct(), and hex().

1x=34
2print(bin(x))
3print(oct(x))
4print(hex(x))
0b100010
0o42
0x22

4.2.3. Integer operations#

Python offers the standard arithmetic operators, as well as a couple of special operators to support division

Python operation

Arithmetic
operator

Example

Result

Addition

+

5 + 2

7

Subtraction

12 - 5

7

Multiplication

*

3 * 4

12

True division

/

16 / 5

3.2

Floor division

//

16 // 5

3

Remainder (modulo)

%

16 % 5

1

Exponentiation

**

2 ** 10

1024

Addition, subtraction, and multiplication are straightforward as expected, and you can include as many numbers and operators as needed within an expression:

1print(5 + 2)
2print(12 - 5)
3print(1 + 2  + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10)
4print(3 * 4)
5print(2 * 2 * 2)
7
7
55
12
8

Division has two distinct operators:

  • True division /, which always returns a floating-point number, even if the number is divisible without any remainder

  • Floor division //, which always returns an integer and drops any remainder.

1print(5 / 2)
2print(4 / 2)
3print(type(4 / 2))
4print(5 // 2)
2.5
2.0
<class 'float'>
2

% produces the remainder of a division operation

1print(5 % 2)
1

Division by zero is not allowed. The Python interpreter will raise a ZeroDivisionError.

16 / 0           # raises ZeroDivsionError
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
Cell In[13], line 1
----> 1 6 / 0           # raises ZeroDivsionError

ZeroDivisionError: division by zero

** is the exponential operator, which raises one value to a power of another

\(5^2 = 25\)

15**2
25

The associated values with an operator (e.g. *,+,etc.) are called operands.

4.2.4. Precedence#

Python follows the standard rules for precedence: (PEMDAS)

  1. Parenthesis

  2. Exponent

  3. Multiplication or division

  4. Addition or subtraction

If there is any confusion, use parenthesis to make your code readable. Confusing expressions are for social media arguments, not computer programs that must be maintained.

12 + 2 * 4
10
1(2 + 2) * 4
16
110 * (10 + 1) / 2
55.0

4.2.5. Example: Temperature Conversion#

In mathematics, we use a formula to carry out special operations such as converting Fahrenheit numbers to Celsius. \( (F - 32) * 5/9 = C \)

However, in Python and other computing languages, assignments are made to a variable on the left side of the assignment operator.

1f = 77
2c = (f - 32) * (5 / 9)
3print(c)
25.0

Step through this code on PythonTutor

Notice that the final type of the value was a float type due to the true division operator.

Brain teaser: Four fours is a puzzle to see how many different numbers you can produce using four fours with an expression.

For example: print("4 + 4 - 4 - 4:", 4 + 4 - 4 - 4) prints 4 + 4 - 4 - 4: 0

How many numbers can you produce? Put additional statements in the cell below with your answers.

1print("4 + 4 - 4 - 4:", 4 + 4 - 4 - 4)
2print("4 // 4 - 4 + 4:", 4 // 4 - 4 + 4)
3# Produce more numbers here
4 + 4 - 4 - 4: 0
4 // 4 - 4 + 4: 1

4.3. Floats#

Floating point numbers (floats) are roughly the set of real numbers ((\( \mathbb{R} \)) - numbers that have decimal points. (We use “roughly” as not all numbers in the space can be precisely defined due to how computers represent these numbers - see below for more details.)

Examples:

110.
10.0
110.0
10.0
1010.0
10.0

Floating-point numbers can also be represented in exponential/scientific notation:

110e0
10.0
110e2
1000.0
110e-1
1.0

As with integers, we can use underscores _ to separate digits for clarity.

11_000_000.023_123
1000000.023123

Operators and precedence rules are the same for floats as for ints. The most significant difference is floor division // which returns a float.

110 // 2
5
110.0 // 2.0
5.0

You can mix and match float and int types in operations. However, the result of any operation that contains at least one float or true division operator will be a float.

15 + 10 + 25.3
40.3

4.3.1. Compound Interest#

A basic financial concept is adding interest to a principal amount after a certain time (e.g., one year). \( amount = principal + (principal * rate) \)

1principal = 1000
2rate = 0.075
3amount = principal + (principal * rate)
4print(amount)
1075.0

Step through this code on PythonTutor

4.3.2. Representation#

As with most other programming languages, Python uses IEEE Standard 754-2008 for floating-point representation and arithmetic.

The Python tutorial discusses some of the issues and limitations of float point arithmetic. As discussed with integers, the underlying numbers behind the representation are binary. Only fractions that involve powers of 2 are represented precisely). Other fractions produce infinitely repeating significands.

From a financial technical perspective, we must use exact representations for our numbers. Python provides the decimal class that we can use in the financial applications that we build. We demonstrate a basic usage of this class below and will have a separate module covering this in more detail.

Examples of incomplete representation:

1(80 - 32) * (5 / 9)
26.666666666666668
1print (1.1 + 2.2)
3.3000000000000003
1from decimal import *
2print (Decimal("1.10") + Decimal("2.20"))
3.30

4.4. Type Conversions#

Python provides several built-in methods to convert values among integer, float, and string datatypes.

int() converts a string or a float to an integral value. The string must be a valid int value. Otherwise, a ValueError occurs. With floats, the decimal portion is truncated (not rounded).

1x = int(5.75)
2print(x)
3type(x)
5
int
1x = int("1842")
2print(x)
1842
1x = int("25.234")   ## Raises a ValueError
2print(x)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[36], line 1
----> 1 x = int("25.234")   ## Raises a ValueError
      2 print(x)

ValueError: invalid literal for int() with base 10: '25.234'

int() also provide an optional argument to specify the base of the number to convert.

1x = int("110",2)
2print(x)
6

And if you are a fan of Andy Weir’s Project Hail Mary, you can even use base-6 (senary) numbers:

1int ("42",6)
26

Unfortunately, Python does not offer a built-in function to convert integer values to strings with ad hoc bases besides 2, 8, and 16. We will leave writing that function as an exercise for the reader in a later notebook.

Unlike integer literals, with string conversions, integer values can start with leading zeros. The string representations for the int() function do not include base prefix such as 0x0F or 0b01. As such, the parsing is more straightforward since bases are explicitly passed in an optional function argument (by default, in the case of base 10).

1x = int("0024")
2print(x)
24
1# the following will produce a "ValueError" - bases must be explicitly provided if not decimal/base 10
2x = int("0x0F")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[40], line 2
      1 # the following will produce a "ValueError" - bases must be explicitly provided if not decimal/base 10
----> 2 x = int("0x0F")

ValueError: invalid literal for int() with base 10: '0x0F'

Python allows the base prefixes (0b,0o,0x) to optionally be used if the appropriate base is supplied as an argument.

1x = int("0F",16)
2print(x)
3x = int("0x0F",16)
4print(x)
15
15

float() converts an integral value or string to a float value. The string must be a valid float value. Otherwise, a ValueError occurs.

1x = float(5)
2print(x)
3type(x)
5.0
float
1x = float("25.234")
2print(x)
25.234
1x = float("alphastring")   # Raises a ValueError
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[44], line 1
----> 1 x = float("alphastring")   # Raises a ValueError

ValueError: could not convert string to float: 'alphastring'

4.5. Minimum and Maximum values#

Theoretically, Python 3 no longer has any minimum or maximum values for integers. Python 2, which has been sunset, used 32-bit or 64-bit representations for integers and did have limits. Practically, a limit exists as to how large integers can be for the interpreter to handle based on the CPU speed and memory.

1x = 2**1024
2print(x)
3print(x.bit_length())
179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216
1025

However, for floating-point numbers, Python does have upper and lower limits. You can see those limits by executing the following block:

1import sys
2sys.float_info
sys.float_info(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, mant_dig=53, epsilon=2.220446049250313e-16, radix=2, rounds=1)
1x = 2.0**1024   # raises an overflow error
2print(x)
---------------------------------------------------------------------------
OverflowError                             Traceback (most recent call last)
Cell In[47], line 1
----> 1 x = 2.0**1024   # raises an overflow error
      2 print(x)

OverflowError: (34, 'Result too large')

4.6. Shorthand Assignments#

As with many other programming languages, Python provides shorthand assignments for operations:

Operation

Shorthand

Meaning

Addition

x += 2

x = x +2

Subtraction

x -= y

x = x - y

Multiplication

x *=3

x = x * 3

True division

x /=2

x = x / 2

Floor division

x //= y

x = x // y

Remainder (modulo)

x %= 2

x = x % 2

Exponentiation

x **= 5

x = x**5

Python does not support the unary increment / decrement operators such as x++ or x--.

1y = 10
2y **= 2
3y
100
1y %= 75
2y
25

4.7. Suggested LLM Prompts#

  • Explain how integers are stored in a computer. What do the different bases mean? How do I convert between these different bases?

  • Provide 7 examples where octal numbers are used in computer examples. Provide examples in Python.

  • Explain operator precedence for Python programming. Why does addition not have a higher priority?

  • Explain floating point representation.

  • Using finance topics, provide 5 examples of when I should use an integer, 5 examples of when I should use a floating-point number, and 5 examples of when I should use a string.

  • Write a tutorial on operators in Python.

  • Walk me through step by step using operators in Python to perform financial calculations.

4.8. Review Questions#

  1. What are the exact literal values of the Boolean data type?

  2. How do you convert other data types to Boolean?

  3. What is the difference between true division and floor division?

  4. What is the data type of the following expressions:

    • 5 / 2

    • 5 // 2

    • 5 / 2.5

    • 7 // 2.5

  5. Explain the precedence rules in Python. Provide an example with multiple operators.

  6. What are the minimum and maximum values for integers in Python? For Floats?

  7. What error occurs if you try to convert the literal value "Python" to an integer?

  8. Fragments of code that calculate new values are called:

    1. assignment statements
    2. clauses
    3. expressions
    4. identifiers
  9. What does “hex” mean?

    1. Base 4
    2. Base 8
    3. Base 16
    4. Base 64
  10. Which of the following are represented numerically?

    1. Images
    2. Sound
    3. Video
    4. All of the above
  11. What is the type of this expression? 5 + 2 + 34 + 4/2

  12. What is the type of this expression? 5+ 8//2

4.9. Drill#

In a terminal window, open a python interpreter shell (i.e., execute python3 or python). Then perform the following operations:

  1. Create a variable named pi and assign 3.14159 to it.

  2. Next, create a variable named radius and assign a value to it.

  3. Now, create a variable named area and assign the expression of pi * radius * radius to it.

  4. Print area to console.

  5. Check the type of area using type()

  6. Compute the circumference of the circle from the variable radius. Create a variable and print that variable.

  7. Create var_one with a value of 10 and var_two with a value of 3

  8. Compute:

    1. var_one plus var_two and assign to var_plus. Print var_plus

    2. var_one minus var_two and assign to var_minus. Print var_minus

    3. var_one times var_two and assign to var_times. Print var_times

    4. var_one divided by var_two and assign to var_div. Print var_div. Print the type as well.

    5. var_one modulo var_two and assign to var_mod. Print var_mod. Print the type as well.

answers

4.10. Exercises#

  1. Write python code to convert 100 degrees Celsius to Fahrenheit.

  2. An internet coffee shop sells coffee for \(\$\)12.85 per pound. The shipping cost is \(\$3\).25 per pound plus a flat handling fee of \(\$\)2.50 per order. Using a variable named coffee_lbs, write a python statement that will compute the order cost and assign the value to a variable named cost. Then print that variable to the console.

  3. Find the formula for periodic compounding. Write a snippet of python code that you can use to set the variables to apply the compounding formula. The code will be similar to the Fahrenheit conversion above, with a few more variables. You should have the following variables with P, r, n, and t where

    • A is the final amount

    • P is the original principal sum

    • r is the nominal annual interest rate

    • n is the compounding frequency

    • t is the overall length of time the interest is applied (expressed using the same time units as r, usually years).

  4. How would you find the additional information for decimal class(type) within Python?

  5. How would you find the additional information for decimal class(type) on the web?

As a reminder, within Jupyter notebooks, we can also add ? after variable or type name to get help. Try in the cell below: