Today's task is to create a program, usable as a calculator substitution. Because of the Delphi are used to work with texts in edit boxes (type: string), we have convert them to numbers first. For the Integer numbers, we can use the StrToInt and IntToStr function.

For an example: declare the i variable as an integer, s as a string (of characters) - example is in the standard Pascal:

vari : integer; s : string;begins := IntToStr(i); i := StrToInt(s);

Please note, that function parameters are in parenthesis
(rounded brackets, (, ) ). On the left side of the assignment
sign (**:=**) cannot be any function.

If we don't like to declare a new variable, we have to make both conversions on one line.

Task: Create a program with two Edit boxes and a button for a sum (+). After clicking to this button, content of the both edit boxes will be converted to integer values, then summed, and then the result will be converted back to one of edit boxes.

At the first, create (visually) a Form1 content:

You can make the Button1 narrower and using the Object Inspector (F11), set a "Caption" property to "+" (plus sign). The Edit1 and Edit2 property "Text" set to "0" (zero). Then you can double-click to button (on the Form1 graphic = visual preview) and add the following handling:

Form1.Edit1.Text := IntToStr(StrToInt(Form1.Edit1.Text) +StrToInt(Form1.Edit2.Text));

*Note: if we are ***inside***
the Form1 variable (literally - if you check the procedure
definition in the first "type" chapter, where is the
Form1 declared, you can see the declaration of the procedures -
as a part of the form itself), we don't need to start the name of
each variable with "Form1.". In the next text, this
(Form1.) will be only if these help to make text more
understandable. The previous can be written as:*

Edit1.Text := IntToStr(StrToInt(Edit1.Text) +StrToInt(Edit2.Text));

Text from each of the edit boxes is converted to number, the results are summed, the sum is converted back to string, which can be assigned to the Text property of the Edit1 component.

Now, you can do the same for the multiplication ( * ) and subtraction ( - ). To the Edit, a number can be written including minus sign ( - ).

*Note: Most important keyboard combinations for programmers
are Ctrl+C and Ctrl+V. Now, this is a good time to train.*

To divide is more complicated. For integer numbers, we have integer divide and the "modulo" (division remainder, residuum). In the Pascal, we use special keyword for evaluating this:

i := jdivk; {the whole part or the integer part of the result} l := jmodk; {remainder, the amount "left over" after the division}

Before and after the **div **and **mod**
has to be some separator, if there are no parenthesis or so, you
have to write a space there. To solve integer division, we could
try to use two commands (note the semicolon):

Form1.Edit1.Text := IntToStr(StrToInt(Form1.Edit1.Text)divStrToInt(Form1.Edit2.Text)); Form1.Edit2.Text := IntToStr(StrToInt(Form1.Edit1.Text)modStrToInt(Form1.Edit2.Text));

But it cannot works, because of the first will change the
Edit1 value, and the second will result to wrong number. To solve
this, we need to keep the original value to some *local
variable*, in this case the "s", which will be
declared *before* the **begin** keyword:

procedure TForm1.Button4Click(Sender: TObject);vars : string[33];{maximum number length - 10 should be enough}begins := Form1.Edit1.Text; Form1.Edit1.Text := IntToStr(StrToInt(s)divStrToInt(Form1.Edit2.Text)); Form1.Edit2.Text := IntToStr(StrToInt(s)modStrToInt(Form1.Edit2.Text));end;

The local variable is created by the each procedure entering, always with the new random content. Please, not to be confused by the Delphi debugging environment, where the new variables are often set to zero at the program start. After program execution (translated .exe file without Delphi), there will be "random" value (the memory will be reused after previous program).

Note. In the text of the examples, the shadow text represents either generated text, or the previous step of algorithm creation.

You can just change the transform function to StrToFloat and
FloatToStr. The type in the Pascal is *real.* Part of the
real number can be a decimal point, or an exponent part (the
"e", followed by a number, or "-" and a
number). There can be no spaces inside a number.

Examples:

3

6,25

-4,7

67,56757898e-27

-83,0568707e3

Pascal converts lowercase and uppercase, so the "e" can be "E". The real number division is written as the slash ( / ). If you divide two integer using a /, the result is a float (real). Task: Change your program to work with a real (floating point) numbers.

The functions have their arguments in the parenthesis and can be used in expressions. The predefined functions are:

sin(x) | sinus; counts in radians |

cos(x) | cosinus |

arctan(x) | arcus tangents |

ln(x) | natural logarithm |

exp(x) | the e^{x} function |

sqr(x) | x^{2} |

sqrt(x) | square root of x |

pi | the pi constant ( π ) |

Now, we can create buttons for these functions. For example, to calculate a sinus function value from the Edit1 value in radians, we can use:

Form1.Edit1.Text := FloatToStr(sin(StrToFloat(Form1.Edit1.Text)));

And for the pi ( π ) constant:

Form1.Edit1.Text := FloatToStr(pi);

Task: add some buttons for the pi constant, and the sin, cos, ln, exp and arctan functions. Note, that computer calculate with radians; if you are preferring degrees for angles, use some conversion, for example sin(x/180*pi) .

A little of theory: the assignment command has the expression on the right side of the assignment sign ( := ). It can be some kind of calculation, created from combination of variable names, values and connected by operators.

**Priority of the operation**

The operation will be solved in this order:

- anything in parenthesis (round brackets). It allows us to control the priority.
- unary operation (negative sign for numbers, the
**not**for logical values or results) - multiplication level (operators *, /,
**div**,**mod**,**and**) - summarization level (+, -,
**or**,**xor**) - comparison level (<, >, <=, >=, =, <>)

On the same level, the expression will be evaluated from the left to the right.

A few examples (all the variables have been declared as a real):

x := sin(pi /3); y := cos(alpha + beta); z := exp( ln(a) *b); {general power} a1:= sin(alpha)/cos(alpha); {tangents} a2:= arctan(sqrt( 1-sqr(x)) / x); {arccos} h := (c*d + e*(f-1) +g)/(c*c + d*d); x1:= (-b+sqrt(sqr(b)-4*a*c))/2/a; x2:= (-b-sqrt(sqr(b)-4*a*c))/(2*a);

Typical floating point variable types in the Delphi from version 2.0 to 7 are:

type | number of the valid digits | size in memory |

single |
7 to 8 | 4 |

real48 |
11 to 12 | 6 |

double |
15 to 16 | 8 |

extended |
19 to 20 | 10 |

You can use the **real** type; this is a generic
equivalent, in older version linked to real48, later being the
"double" equivalent.

The single has been used for big matrix, for example in simulation. The evaluation of the expression itself is solved in the numerical part of the CPU, where all the computation is solved as extended or double, so there is no difference in speed of evaluation; but there still can be better speed of memory operation, or transfer of the data by network. (The transfer speed of the 8-byte variable on the 64-bit type processor can be faster, if it corresponds with the memory alignment; most of compilers ignore this, typically aligning only to words (2B), so the shorter variable can be probably faster).

**Conversion function**

If the right side of the assignment command (expression) has an integer type and the variable on the left side is typed as real, the automatic conversion will be invoked. In the opposite, programmer has to choose a conversion function (variable types in the next example: i - integer, x - real):

x := i; {automatic conversion} i := round(x); {rounding, down for <0.5, up for >=0.5} i := trunc(x); {only the whole part, without a fraction - to zero direction, i.e. -3,9 to -3}

The round function can be used even for rounding to some amount of decimal digits after decimal point separator, for example 2:

x := round(x * 100)/100;

The **var** keyword for the variable declaration
can be on the two distinctive positions: if you create a new
Delphi application, you can try to read through source and find
the first possible **var** appearance:

var Form1 : TForm1;

There we can add a new variable declaration as a new line
after the semicolon. If we declare a variable here, it can be
used from any procedure and will keep its value during whole
program running. This is so called **global variable**.*
**Note.*

The opposite is the **local variable**; it will
be created in the shared memory, when the procedure starts, and
this memory will be given back after finishing. When the
procedure is run again, in each start all the variables will be
created (not literally - they are mapped by the compiler on the
processor stack relatively, but in the same place for more
procedures). So - after reentering a procedure, new initial
values will appear in all the variables; only variables with a
start value declared will be initiated, but this is slow.

For the second (local variable declaration), we have to add
the **var** keyword as a new line between the **procedure**
and the **begin** directives.

Example:

procedure TForm1.Button1Click(Sender: TObject);varx,y : extended; i : integer;begin{some program code}end;

Task:

Modify your program to use local variables. For example,
we can transfer the Edit1 and Edit2 contents to variables, then
we can do the mathematical operation, and then convert back (the
grey texts have been produced by the Delphi by a doubleclick to a
button):

procedure TForm1.Button1Click(Sender: TObject);varx,y : extended;beginx := strtofloat(form1.edit1.text); y := strtofloat(form1.edit2.text); x:=x+y; form1.edit1.text := floattostr(x);end;

In this case, it can be more readable, but probably slower and memory consuming. Better task:

Declare a global variable M (type extended) and use it as a memory (the M+, M-, MS, MR and MC button).

Part of a solution: The M+ button can be solved as:

M := M + strtofloat(form1.edit1.text);

The M reading will be solved as:

form1.edit1.text := floattostr(M);

*The solved tasks from this exercise are in the **file
"cisla"** (in Czech). *

Note: For this type of program there are important to keep the cursor in the Edit2 component, but this is moved to the last button we use. To solve this, we can set up a "focus" by the command:

Form1.edit2.text.setfocus;

It will move cursor to the Edit2 component. Important is, that this command has to be as the last line of all procedures form this calculator.

Note 2: This kind of tasks is a good training for use of Ctrl+C and Ctrl+V (originally Ctrl+Insert and Ctrl+Shift), which are the most important key combination for a programmer.