- ←
- Remove the
#include
directive in 01a-hello-world.ox
and see what happens.
- Open
02-fix.ox
in OxEdit and run it. It should produce an error. Explain why.
- Explain why the program below is not a complete Ox program.
program() { decl x; x = 5; }
- ←
- Mark each of the following as valid or invalid Ox identifiers
Valid Invalid
-----------------------------------------
a
a1
1a
a_1
_a_1
doit!
b c
ABC
a-b
------------------------------------------
- Run this file.Note the error that is created. Change the code so that it prints out 5.0.
02a-fix-error.ox
1: #include
2:
3: main() {
4: decl println=5.0;
5: println( println );
6: }
- Open the code below in OxEdit. Fix the errors with comments so that it prints out
hello world
.
03-fix-errors.ox
1: #include "oxstd.h"
2: */ A comment /*
3: /*
4: main() {
5: // println(
6: "hello, world"
7: );
8: }
- Write a program named twomatrices that stores these matrices in a program and prints them out to the screen. (Note: "1/2" is just another way of writing "0.5" so in all cases you are storing numbers in the matrix.
$A= \l(\matrix{1&2&3\cr 4&5&6}\r)\qquad$ $B=\l(\matrix{1/2&0\cr 0 & 1/2\cr}\r)\qquad$ $C = \l(\matrix{-1\cr 0\cr 1}\r)$
- Create an Ox program named diag.ox.
- Have it create a matrix in $D$ which is a 4×4 diagonal matrix with the diagonal equal to <1 2 3 4>. (Look up diagonal matrix on wikipedia if you aren't sure what it means.)
- Use the Ox help documentation to find a function that will create the same matrix in $D2$ for you by sending the diagonal as a vector to it. Print out the matrix to verify it works.
- Use Ox help to find the way to extract the diagonal from a matrix and apply it to the matrices $A$ and $B$ in the previous exercise.
- Use Ox help to find a function that will create a new matrix from $A$ that is diagonal (sets off-diagonal elements to 0). Print out the function output to check it
- Look up the definition of a band matrix,
https://en.wikipedia.org/wiki/Band_matrix
. Create a 5×5 band matrix with -1 below the diagonal, 2 on the diagonal, and +1 above the diagonal.
- Write a program that creates a constant array of titles or names or places, etc. Use
enum{}
to define a best and worst in the list and print them out. That is, best
would be the index into the list that is the best (in your opinion). For example, I might create a list of some Canadian music artists:
Joni Mitchell, The Band, Tragically Hip, Nickelback, Celine Dion, Drake.
For me, I would define best
as 1 and worst
as 3 in that list (although technically the Band is only 4/5ths Canadian, eh).
- Here is the mapping of letter grades to course percentage and GPAs at Queen's.
enum text 100-point-scale GPA
------------------------------------------
F F 00 0.0
Dm D- 52 0.7
D D 55 1.0
Dp D+ 58 1.3
Cm C- 62 1.7
C C 65 2.0
Cp C+ 68 2.3
Bm B- 72 3.0
B B 75 2.7
Bp B+ 78 3.3
Am A- 82 3.7
A A 87 4.0
Ap A+ 93 4.3
Below is the start of an Ox program that creates enum "aliases" for the letter values, their text and their values. Complete the elements started and then add more print statements to check that it works.
03d-letter-grades.ox
1: #include "oxstd.h"
2:
3: enum{F}
4:
5: const decl
6: gtext = {"F" } ,
7: gpct = <0 >,
8: gpt = <0.0 > ;
9:
10: main() {
11: println(gtext[F]," = ",gpct[F],"%. and GPA = ",gpt[F]);
12: }
Because enums create identifiers they can't have symbols like "+." So the text column is what you would want to be printed out for the grade. The other two columns are numerical values associated with each letter grade. You would add items separated by commas to each constant already started. Then the program can be used to process grades in different ways.
- ←
- Look up the built in Ox function max(). Go to the Example of its use. Copy that program to a new .ox file in Oxedit. Run the program until you get the same output as the documentation claims.
Then, change the arguments sent to
max()
and rerun it so that you understand what max()
does. Once you feel comfortable, compare what max()
does with maxc()
, which is a different function. Compare the output of max()
and maxc()
when both are sent the matrix < 1, 2, 3; 4, 5, 6>
.
- Use the Ox Help index to find out what symbol is used for the
Kronecker product
(a matrix operation not needed in this class, just used as an example for finding help.)
- ←
- Find out why discovering mistakes in a program is called debugging.
- Open the code below. Go through the edit/compile/debug/execute/debug cycle, until the program runs and produces correct output.
04-bang-head-wall.ox
1: &include "oxstd.h'
2: main {
3: decl y;
4: x = 5.0;
5: println("x = " x);
6: }
- ←
- This program outputs the number 0.1:
04c-OneTenth.ox
1: #include
2: main() {
3: //Step 0.
4: println("1/10 = ",0.1);
5: }
Keep adding code to the program to do the calculations below and re-running it, fixing errors until the output is correct. Put a comment like the one above before each code step.
- Augment the program to print out
0.1
four more times based on have 4 different expressions that evaluate to 0.1:
- scientific notation (e.g. 2E1=20)
- using
/
in an expression that evaluates to 0.1
- using
^
- using
sqrt()
.
- Now store 0.1 in a variable
y
. Print out the values of $\ln y$, $y^2$, $y^y$, $1/y$, $e^y$, and $e^{-y^2/2}$. Find the built-in Ox functions and operators necessary. In each case, print out a string to identify the expression, like println("1/y=",1/y);
.
- Copy and paste the lines for the previous step's calculations. In between the two copies, re-set the value of $y$ to equal the matrix $\l(\matrix{1&2\cr 3&4}\r)$. Observe what happens when you apply those operators to a matrix. If any of the operators generate an error when applied to a matrix try replacing it with the "dot" version and observe the result.
- Create a program in a file named AopB.ox. Let $A= \l(\matrix{1&2\cr 3& 4}\r)$ and $B = \l(\matrix{1&-1\cr 0& 1}\r)$. Create variables with those values. Print out the result of these Ox matrix operations. Make sure you understand what each operation does:
- A*B
- A.*B
- A+B
- A./B
- A/B
- A.^B
- Write a program that computes the expression in equation (A), $\log({e^{2.2}\over 1+e^{2.2}})
+ \log({1\over 1+e^{-0.7}}) $. Verify with a calculator.
- Go to the Ox documentation (help). Find the table of "Operator Precedence" and determine whether "concatenation" operations are carried out before "additive" operations.
- Create a program in a file named vecops.ox. Use vector operations and built-in Ox functions to compute and print out expressions of two $n\times 1$ vectors, $x$ and $y$:
$$\eqalign{
&\sqrt{{\sum}_{i=1}^n \left(x_i-y_i\right)^2}\cr
&{\prod}_{i=1}^n\ x_i^{y_i}\cr
&{1\over n}{\sum}_{i=1}^n\ e^{ -(x_i-y_i)^2 / 2 }\cr
}\nonumber$$
Test your expressions for $x = \l(\matrix{0.1\cr 1.4\cr 0.8}\r)$ and $y= \l(\matrix{0\cr -1.2\cr -0.6}\r)$. Use a calculator or some other method to check the output.
- Explain the output of this program including warnings.
04b-vecwarn.ox
1: #include "oxstd.h"
2: main() {
3: decl v = <0; 1; 2>;
4: v[1] = 4;
5: println("v=",v);
6: decl A = <0, 1; 2, 3>;
7: A[1] = 4;
8: println("A=",A);
9: }
- Recall the program you wrote to encode the Queen's letter grade system.
Add a statements to compute the GPA and percentage averages for 2 letter grades with enum values
Am
and Cp
. Print out the text of the grades and the resulting GPA and percentage.
- Explain the difference between postfix and prefix incrementing and decrementing by explaining the output of this program
04a-increments.ox
1: #include "oxstd.h"
2: main() {
3: decl i;
4: i = 5;
5: println("A. ",i);
6: println("B. ",i++);
7: println("C. ",++i);
8: println("D. ",i);
9: println("E. ",--i);
10: println("F. ",i--);
11: println("G. ",i);
12: }
- Here is a matrix and an ox code
5.1 6.2 -1.15
0.2 0.4 0.0
0.0 -3.0 0.0
0.8 1.6 0.0
-9.2 -3.1 2.4
06a-matrix-io.ox
1: #include "oxstd.h"
2: main() {
3: decl m;
4: // create matrix given
5: // save to a file
6: // load matrix back in, print out result
7: }
- Store the matrix in the variable
m
. Look up the savemat()
function. Use it to save $m$ to a file named m.mat.
- Look up
loadmat()
to load the matrix back into another variable m2
. Print out m2
to check that it worked.
- Open the file m.mat in Oxedit. Try to understand the format of the file and how it relates to the matrix you saved to it. Then look up the Ox help information for
loadmat()
and see if the explanation for a .mat
matches what you learned from looking at one.
- Edit the file m.mat by switching the two numbers on the first line and save the file. Then comment out the
loadmat()
statement so it doesn't happen and re-run to see what happens when you print out m2
.
- ←
- Open the program below. It asks the user to enter 6 numbers and store them in a 2×3 matrix. Modify the program by adding another
scan()
call that asks for the number of rows and columns first; then prompts for r*c numbers; and then stores them in the desired r×c matrix.
06-scanM.ox
1: #include "oxstd.h"
2: main() {
3: decl x, r=2, c = 3, N=r*c;
4: println("Enter ",N," numbers separated by spaces then ENTER");
5: scan("? %#m",r,c,&x);
6: println("Ok, x= ",x);
7: }
- Open the program below. It asks the user to enter a temperature in Fahrenheit and convert it to Celsius. It then prints out a comment on the temperature.
07a-FtoC.ox
1: #include "oxstd.h"
2: main() {
3: decl TF, TC;
4: scan("Enter Fahrenheit temperature: %g",&TF);
5: //TC = insert-code-to-convert-to-Celsius
6: print("Ok, ",TF,"F = ",TC,"C ");
7: if (TC<0) println("burrr");
8: }
- Look up the conversion formula F to C and implement on the commented line
TC = ...
. Input the temperatures: -5, 33, 212; use another conversion tool (Google, calculator) to verify the output.
- Add a message that if the temperature is above 30C says
hot!
.
- Add a message that between 0 and 30 says
nice
.
- Notice there are two constants in the F to C conversion: the freezing point in F and the temperature ratio between F and C. And you can use them to convert back-and-forth between F and C.
07b-Fever.ox
1: #include "oxstd.h"
2:
3: // Use const to store constants that appear in formulas, equations, etc.
4:
5: const decl FP , ratio ;
6:
7: main() {
8: decl T, TF, TC,scale;
9: scan("Enter temperature : %g",&T,"%s",&scale);
10: if (scale=="F") {
11: //set TF and TC when T is in Fahrenheit
12: }
13: else if (scale=="C") {
14: //set TF and TC when T is in Celsius
15: }
16: else
17: oxrunerror("scale not recognized");
18: print("Ok, ",TF,"F = ",TC,"C ");
19: if (TF>100.4)
20: println(" Fever ");
21: else
22: println(" Normal ");
23: }
- Modify this code to store the two constants.
- This version also modifies
scan()
so that it asks for both a temperature and a character for the scalar:
scan("Enter temperature: %g",&T,"%s",&scale);
Use the constants inside the if() else
to convert from F to C or C to F. Each branch sets the values of both TF and TC so they store the same temperature in each scale. No numbers should appear, just T, FP and ratio.
- Modify the function so that the code in the two branches are moved to two functions,
FtoC(tf)
and CtoF(tc)
. Each takes a temperature as its argument and returns the converted temperature. Use this function instead of the inline code.
- Create a flowchart for the following plan: if rain is forecast for the day take an umbrella to work. If rain is not forecast but it is raining hardon the way home buy an umbrella at the corner store.
- Use
scan("%g",&x)
in a program to prompt the user to enter a real number. If it is bigger than 0 print out the logarithm of x. If it is less than or equal to 0 return a message that says the log of x is undefined.
- Use scan to enter a number
x
and the conditional expression ? :
to store in another variable 0
if x < 10
, 1
if 10 ≤ x < 100
and 2
if x ≥ 100
.
- ←
- Based on the program below use a
while()
loop to compute the sum value of a vector then print it out.
09a-Sum.ox
1: #include
2:
3: main() {
4: decl v, i, S;
5: v = < 3;2;6;-1;5>;
6: // initialize
7:
8: while ( /* condition */ ) {
9: //body of loop
10:
11:
12: // increment
13: }
14:
15: // continue
16: println("S = ",S);
17: }
- Use a
while()
loop to compute the largest (max) value in a vector then print it out. Use this logic: If the vector only has one element then its first (and only) value is the largest. Then if it has more than 1 element, check each element against the current max. If it is bigger it becomes the max.
- Given two vectors, $V$ and $X$, of the same length, consider the count of how many of the $V$ elements are bigger than the corresponding $X$ elements. Write it as a mathematical expression involving $\sum$ and $I\{\}$ Then write a flowchart to implement the expression following the examples of counting positive numbers in a single vector.
- Recall the
while()
loop to compute the average value of a vector. Re-program it to use a for()
loop instead.
- Re-program the
while()
loop to compute the largest value in a vector to use a for()
loop instead.
- If $A$ and $B$ are two $n\times m$ matrices then the sum $C = A+ B$ is the matrix of the sum of the correspondingly elements. Create two matrices and write a
for loop
to create their sum.
- ←
- In the Ox Syntax Reference find the
GOTO
statement. Below is code to print the first 50 non-negative integers using if()
and goto
. Move the label TOP
so that this becomes an infinite loop. And then replace the loop with a correct for()
loop.
10-goto-no-no.ox
1: #include "oxstd.h"
2:
3: main() {
4: decl i;
5:
6: :TOP
7: println("start");
8: i = 0;
9: if (i<50) {
10: println("i= ",i);
11: ++i;
12: goto TOP;
13: }
14: }
- ←
- OOPS! Run the program below and explain the output. Come up with other expressions that result in
.NaN
or .Inf
.
12-fpr-lims.ox
1: #include
2: #include
3: main(){
4: decl x;
5: println("Extreme Calculations in Ox\n");
6: println("1. Ways to produce numerical Infinity and 0:",
7: "\n log(0) = ",log(0),
8: "\n 1/0 = ",1/0,
9: "\n 1/log(0)= ",1/log(0));
10: x = 0/0;
11: println("2. Ways to produce NaNs: x = 0/0",
12: "\n x =",x,
13: "\n x+5 =",x+5,
14: "\n 1/log(x)=",1/log(x));
15: println("Precision around 1.0:",
16: "\n 1-DBL_MIN =","%25.23f",1-DBL_MIN,
17: "\n 1-epsilon =","%25.23f",1-DBL_EPSILON);
18: println("Checking for NaNs in your code:");
19: if (isnan(x)) oxrunerror("Big problems with my project: Check value of x!");
20: }
- Run
11-numlims.ox
and explain the output. Explain the relationship between these pairs of machine limits:
DBL_MAX and DBL_MAX_E_EXP
DBL_MIN and DBL_MIN_E_EXP
DBL_DIG and DBL_EPSILON
- ←
- What output will be produced by
seven.c
? By sevenb.c
?
- ←
- The program below reads in a spreadsheet also in the code folder which contains one year of temperature data from U. of Waterloo. Notice this shows that Ox's
loadmat()
function can read in spreadsheets and some other kinds of files into an Ox matrix.
15-temperature.ox
1: /* Exercise code by C. Ferrall. See notes for more explanation.
2: */
3: #include "oxstd.h"
4:
5: enum{ day, lo, hi, precip,Ncolumns}
6: const decl
7: clabels={"day#","low","hi","precip"},
8:
9: fn ="Daily_summary_2014.xlsx"; //Source: http://weather.uwaterloo.ca/data.html
10:
11: main() {
12: decl data = loadmat(fn);
13: if (isint(data)) oxrunerror("spreadsheet file not in the same folder as program.");
14:
15: data[][day] += dayofcalendar(1900,1,1); //Adjust dates to Ox's Julian dating.
16:
17: println("First 10 days:","%c",clabels,"%cf",{"%C","%10.1f"}, data[:9][] );
18: println("Max Hi temperature:",maxc(data[][hi]));
19: println("Min Lo temperature:",minc(data[][lo]));
20:
21: // add code here for more statistics
22:
23: }
An aside
The first column of the spreadsheet (and now matrix in Ox) contains an integer value for the day. The data counts days from January 1, 1900. Ox can print out calendar days too, but it uses a different date for day 0. So the program adds the day number of 1-Jan-1990 to the data. Then Ox will print out dates if you use the %C
format. None of this is important for the exercise, but it is included to show that your input and output can be sophisticated.
The program prints out the first 10 days of data. It uses maxc()
and minc()
to find the highest and lowest temperatures that year.
Add code using if()
, for()
and/or built-in Ox functions to compute the following statistics from the data. (I suggest using both built-in functions and your own loops ... compute the same statistic both ways to verify your code).
- The average daily temperature range over the year (difference between high and low temperature each day). A formula for this would be $\sum_{d=1}^{365} {hi_d - lo_d \over 365}$ but you can compute that number different ways.
- The number of days the hi temperature was below 0.
- The number of days the low temperature was above 20.
- The biggest change (in absolute value) in mean temperature from one day to the next over the year.
- The autocorrelation coefficient for average daily temperature (the correlation between today's temperature and yesterday's temperature).
- Extra Credit: prompt the user to first enter either C or F. If they enter "F" then convert the temperature data to Fahrenheit and print out results in Fahrenheit instead of Celsius.
- ←
- Ox functions are not required to have a
return
statement. What happens if a return value is expected but not is set? Find out for yourself by running this program:
#include "oxstd.h"
sayhello() {
println("hello");
}
main() {
decl y;
y = sayhello();
println("sayhello returns ",y);
}
- Use Ox help on functions to find out what value is returned by the following built-in functions:
print() scan()
Modify programs already using these functions to print out the return value of the functions and confirm them.
- An earlier exercise asked you to use a for loop to compute the matrix sum of two matrices. Write an Ox function in this form
matadd(A,B,aSum)
A, B n x m matrices
aSum input address,
output n x m matrix A + B, if well-defined
returns
1 if A + B is well-defined;
0 if not well-defined.
Include a main() function that tests your function on simple input to show that it works.
- You may know that the transpose of a matrix switches rows and columns. The built-in Ox operator ' will transpose a matrix. Write a function in the following form without using that operator.
trans(A)
A input matrix
return A' transpose of A
- The logistic transformation is often used in econometrics. One way it is used is to map a vector of values into probabilities that add up to 1. So if $x$ is a $N\times 1$ vector of numbers then the logistic transformation is a new vector v with values
$$v_i = {e^{x_i} \over {\sum}_{i=1}^N e^{x_i}}.\tag{LogitT}\label{LogitT}$$
- Write a function
logkernel(x)
x n x 1 vector
return
the n x 1 vector logistic transformation of v
Include a main() routine that demonstrates your function. Save the output it produces to a file.
- Once your function works for a column vector, extend it so it can take a matrix X and returns the transformation within each column.
- ←
- Modify
16-plot2.ox
so that multiple indifference curves are produced. To do this change u0
from a scalar to a column vector. (Getting the labels requires changing the third argument of DrawXMatrix.)
- ←
- The program below codes a mathematical operation you are familiar with. It uses a built-in Ox functions to check the result (please look up the function in the Ox function summary, it can come in handy). The code runs and produces verified output for the given values. However, there are no comments, no new lines and no indentation to help a human read the code. Note that it does use one feature that is good coding: it uses
enum
to give labels for elements of the input vector. The tags in the enum
should make sense, or the tags might help you recognize the operation being coded.
- Save a copy of the file to a new one called
17-addstyle.ox
. Using that file modify it to make it readable following the guidelines given in the text, or another style if you have been taught a different way and prefer that. Changes to include: comments, line breaks, and
indentations. Once you start doing that you should be able to figure out what the program is doing. Then give the things in the program (functions and variables) more meaningful names that reflect their purpose.
- Once you have done that, make sure the program still works (you haven't added an error).
- Extra Credit: look in the Ox function summary to find a built-in function related to the one already used by the program that would solve the problem as well. See if you can get it to do the same work as the function in the file. However, note, the documentation is a bit unclear and that function will return the reciprocal of the values we are looking for. If you get that far, try picking new inputs that lead to undefined results for the function in the file but that the built-in function handles just fine.
17-addstyle.ox
1: #include "oxstd.h" enum{c,b,a} q(co){decl rad=sqrt(sqr(co[b])-4*co[a]*co[c]); return (-co[b]+(-rad~rad))/(2*co[a]);}main(){decl myc=<2,3,1>,myr; myr=q(myc);println("coeffs:",myc,"solutions:",myr,"check:",polyeval(myc,myr));}
- Open the code below and run it. Verify a compile-time error occurs. Now move the declaration of the global
y
above the first reference to it and see if the error goes away. Explain why.
18-global.ox
1: #include
2:
3: decl v;
4:
5: f() {
6: v = 5;
7: y = 6;
8: }
9:
10: decl y;
11: g() {
12: y = 7;
13: }
14:
15: main() { }
The program in 19-ping-pong.ox
simulates a popular game played by two or four players.
- Run the program as is. Then stop it by clicking on the STOP but icon on the OxEdit menu (or it may die on its own).
- Add to the code a global variable called
rally
to count how many hits by both sides have occurred so far. Do this by adding statement inside each function that increment rally
.
- Now change the code so the rally ends after 10 volleys.
- [Harder]. Add
#include "oxprob.h"
to the top of the code. Look up the ransubsample()
function. Use ransubsample(1,11)
so that the rally lasts anywhere from 0 to 10 hits.