Previous - Next

Fundamental Concepts

A bit of history

Humanity has always needed to use computation to solve some of the real-life problems. Computations could be as simple as adding two numbers or more complicated such as methods for finding the roots of a function. Virtually all scientific and engineering fields rely on some computational methods to solve their problems. If you are an educator, a physician, an engineer, or even a philosopher, you need to process data and produce information. For example, a teacher may want to know the average grades in a class or all school students. There could be hundreds of numbers, which need to be added up to compute their average. In the old days, some companies and governments recruited people whose jobs were described as computers. A computer used to be a person who received large piles of data and produced information using pencil and paper. As the volume of data and the need for computation grew, the human's job, the error produces, and the long hours needed to do simple computation did not make sense anymore. Motivated by money, and sometimes by winning over enemies, eventually scientists designed digital computers, which used a simple binary system of electrical signals to encode and operate on data. Today, these powerful machines are available as watches, mobile phones, large supercomputers, small devices that are embedded in a human body, and a Pillcam that can monitor cancer tumor in a patient's gut. In these notes, we will study the basics of dealing with computers by writing simple programs that instruct computers to do some tasks. These notes assume no prior computer knowledge except basic usage and assume the reader has a basic college-level understanding of algebra and calculus.

Computer Components

A computer is a device that has multiple hardware components. Each component performs a distinct task. The computer's brain is its Central Processing Unit (CPU) and memory. The CPU performs basic arithmetic and logical operation using the Arithmetic and Logic Unit (ALU). The memory is of two kinds. One is the short-term memory that is cleared out when your program is terminated. Usually, one way to implement short-term memory is using Random Access Memory (RAM). Another type is secondary storage. Modern computers use solid-state drives (SSD), which are very fast but slower than RAM. Larger data is stored on the secondary storage. When needed, parts of the data can be loaded into the RAM. Programming languages often have ways to use both the RAM and secondary storage.

The Role of Languages and Translators

We use programming languages to communicate with computers. We construct sentences that translate to commands for a computer's CPU to execute. These sentences are not immediately understandable by the computer. To bridge this gap, we use a program called the compiler or the translator to translate our program (written in Python) to machine code. As programmers, we write programs, which the compiler will translate to machine code. When we would like to execute the program, the operating system helps us load our program into short-term memory (RAM). When the program is in RAM, the CPU starts executing our program's instructions until the last instruction is executed.

Sequential Execution

Programs consist of lines of code. Each line is an instruction for the CPU to execute to achieve a specific goal. For example, an instruction can be to compute x/y. As a programmer, we specify that we would like to know how to divide x by y. The CPU starts executing these instructions starting with the first line of code in our program. Once the first line of code is executed (without any problems), the CPU goes to the next code line. This sequential execution continues until the last line of code is executed. As we may imagine, the CPU will not correct our mistakes or do things that we did not specify in a computer program. Instead, the CPU will do what we ask, even though what we ask may not be correct. Therefore, it is the program's job to ensure that the program performs what it should do.

Data to Information

A major benefit of computer programs is to transform data into information. Data can be in many forms. For example, you could collect all students' grades at the 10th grade's mathematics course across all public high schools. We may write a simple program to produce the average of all the grades and their standard deviations. Further, we may print the maximum, the median, and the minimum grade for all students. These (and more complicated applications) are the information produced from the programs we write. Special to the Python language, we have many simple and efficient tools in the language that can help us collect and store data in memory, perform the computation that we need, and then print the final information used in our daily work.

Basic Ingredients

The basic ingredients of a computer program are the software and the language tools available to us to write_ and _ _ execute_ programs. A program is a file that contains instructions for a computer to be executed. Executing an instruction means performing the task that was required. For example, we may want the computer to produce the result of dividing 1200 by 67. To do this, we need to write a program that tells the computer to divide. Sometimes we can use existing tools in a programming language to ask the computer to perform a specific operation like division. Sometimes we need to give the computer complex instructions that cannot be expressed simply by tools available in a language. In those cases, we need to supply the computer with detailed step-by-step instructions to execute the task. Once we write the program, we will need to ask the compiler to translate it to machine language and then ask the operating system to execute our program. When executing our instructions, the CPU will not understand what our intentions are. The CPU will perform exactly what we have asked it to do even if our program contained the wrong instructions sequence. For example, we may want to write a program to receive two numbers, x and y from the user and display their sum on the screen. If we, instead, by mistake, ask the CPU to compute x-y and display it on the screen, the CPU will do that. Thus, it's important to make sure that we write programs that follow the correct grammar of the language we are using, and they also ask the CPU to perform what we wish to see as the outcome exactly.

The basic ingredients that we would like to know about are:

  1. Python statements that describe the instructions,
  2. variables and their roles in using the RAM,
  3. expressions to compute values from other values,
  4. conditionals that allow us to tell the computer how to make decisions,
  5. repetition statements that allow us to tell the computer how to repeat some statements, and
  6. files and their roles in utilizing the secondary storage.

Python Statements

A sentence in the Python programming language is called a statement. There are various kinds of statements. The most basic ones that we study first are expressions, which result in values and assignment statements. An assignment has a left-hand side (LHS) and a right-hand side (RHS) and the = in the middle. For example, x = 10 is an assignment statement. This statement asks the CPU to reserve some memory in RAM, give the name x to that memory location, and put the value 10 in x. This does not exactly mean the equality sign we know from algebraic expressions.

Python Expressions

A program must be written in the correct syntax to be translated by the compiler. The correct syntax follows the rules of the programming language. For example, how can a programmer define a name in a program? Naming rules are defined based on the programming language. In addition to rules, there are tools that the Python language gives us to write programs. These tools are keywords, names, constants, and comments. We also learned that names can contain any letter, digit, or _ but cannot start with a digit. Python has a nice shell program, which we can use as a calculator. Starting to write simple programs, we learned that a Python program consists of statements. We learned that there are assignment statements and expressions. Each assignment looks like this: name = expression. For example, x = 52 is correct assignment statement. Each expression must evaluate to a single value, which has a type.

An expression can have arithmetic operators, which are: **, *, /, //, %, +, - (given in the order of precedence). Operator precedence means when we have several operations in one expression, those operations with higher precedence are evaluated first. Expressions can include parentheses (), which have the highest possible precedence. When two or more operators of the same level of precedence show up in one expression, we will prioritize left to right. Note that + and - each have two meanings. When + or - are used as unary operators, they mean positive and negative and have precedence just below **. When used as binary operators, they are treated as addition and subtraction operators and have precedence just below *.

In addition to regular assignments, Python allows for augmented assignments. For example, we can say: x+=5 instead of x = x+5. Do not forget that an assignment does not mean equality. Remember that the value of any variable can change, but constants remain as they are forever.

As an exercise, without using Python, find out what is the value of y and what is the value of x when the CPU finishes the execution of the program below:

x = 1
x = x+1
x = x-2
x = x*2
x/= 2
y = 5
y = y+x

To run this program, we should write it in a Python editor (such as IDLE), save the file, and click on Run.

Errors

An error is a mistake from the programmer in violating a rule. You can have two types of errors in your Python programs. Similar to natural (human) languages, computer programming languages have specific grammar. Those who develop these languages specify how the programmer must write a program's statement correctly. The compiler's major duty is to check the program against the language grammar to conclude if the program has correct syntax (written correctly). If our program is not written correctly, the compiler will produce a syntax error and not translate our program into machine code. Therefore, we will not be able to execute our program.

A syntax error is when you make a mistake in the way you write the program. For example,

x = 2 3
  File "<stdin>", line 1
    x = 2 3
          ^
SyntaxError: invalid syntax

is a syntax error because the program has no meaning to the compiler in terms of the language grammar.

Another type of error that prevents the program from continuing execution is the runtime error. Programs with runtime errors do not have grammar errors but would like to do things that the CPU cannot do. For example, the code below has a runtime error because one cannot divide a number by zero (undefined operation).

5 / 0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero