Lab 1
=====
Get the code
------------
Use the ``curl`` command to download the code you'll need for the lab.
.. code-block:: console
$ curl https://www.phy.olemiss.edu/~kbeach/phys540/src/lab1.tgz -O
$ tar xzf lab1.tgz
$ ls lab1
cpp/ julia/ python/ rust/
$ ls lab1/cpp
binomial.cpp makefile maxint.cpp
$ cd lab1/cpp
*The instructions here focus on C++, but you may carry out the
comparable steps in Julia, Python, or Rust. We'll be exploring all of these languages in this course.*
The file ending in ``.tgz`` is an archived and compressed directory of
files (often called a *tarball* and sometimes bearing the suffix
``.tar.gz``). The last command above moves you into the ``cpp``
directory that is nested inside the ``lab1`` directory.
Hello World!
------------
Start by creating a file ``hello.cpp`` that contains a "Hello World!"
program. See the C++ code listing below. Which text editor you use is
a matter of taste. The editors ``vim``, ``nano``, and ``emacs -nw`` are
good options that operate within the terminal window. Although I like
``vim`` for some tasks, most students will likely prefer a modern editor
with a windowing interface, such as `Atom `_,
`Brackets `_, `Sublime Text
`_, `TextMate `_;
a full-fledged IDE, such as `XCode
`_ or `Visual Studio Code
`_; or a cloud-based notebook in the
style of `IPhython `_ or `Jupyter
`_.
.. code-block:: c++
:caption: lab1/cpp/hello.cpp
#include
using std::cout;
using std::endl;
int main()
{
char a = 'k';
cout << "He" << ++a << "lo World!" << endl;
return 0;
}
Compile it with ``g++`` (or ``clang++``) and run the resulting
executable. You should be able to reproduce the following terminal
session:
.. code-block:: console
$ g++ -o hello hello.cpp
$ ls -F
hello* hello.cpp
$ ./hello
Hello World!
.. code-block:: julia
:caption: lab1/julia/hello.jl
a = 'k'
a = a+1
println("He",a,"lo World!")
.. code-block:: python
:caption: lab1/python/hello.py
a = 'k'
a = chr(ord(a)+1)
print("He"+a+"lo World!")
.. code-block:: rust
:caption: lab1/rust/hello.rs
fn main() {
let mut a = 'k';
a = ((a as u8) + 1) as char;
println!("He{}lo World!",a);
}
All four programs produce identical output.
.. code-block:: console
$ cd ../julia
$ julia hello.jl
Hello World!
$ cd ../python
$ python3 hello.py
Hello World!
$ cd ../rust
$ rustc hello.rs
$ ./hello
Hello World!
Look carefully at the program listings and take note of how the
languages differ in their treatment of the character type and in their
approach to formatting strings/streams for display on the screen. C++
and Julia both treat the character as an integer type and quietly cast
between ordinals and characters as needed. Python and Rust both require
some extra work to effect the conversion. For Rust, in particular, this
is a matter of language philosophy. It is a very strongly typed
language, and all type conversions are explicit.
Each of these languages has its own look and feel, but there are family
resemblances. C++ and Rust are traditional C-style "brace" languages,
with all code blocks enclosed in matching braces and each command
terminated by a semicolon. Layout is free-form, and extra white space is
ignored. (More precisely, any number of spaces, tabs, carriage returns
in sequence is equivalent to a single space.) The instructions to be
executed are enclosed in a function named ``main``.
Julia and Python each have the cleaner, more minimalistic feel of
a scripting language. Semicolons are not needed as a separator. These
languages assume one command per line. And braces aren't used to
organize the code. Instead, Python groups any commands that sit at
a common level of indentation; Julia uses *keyword* ... end blocks, in the
style of ALGOL and Pascal.
Overflow
--------
Compile and run the program ``maxint``. It generates the first six
powers of two, starting from the zeroth.
.. code-block:: console
$ make maxint
g++ -o maxint maxint.cpp -O -ansi -pedantic -Wall
$ ./maxint
2^0 = 1
2^1 = 2
2^2 = 4
2^3 = 8
2^4 = 16
2^5 = 32
Extend the program to determine the largest ``int`` that can be
represented on your machine. Are there differences in behavior between
the C++, Julia, Python, and Rust implementations?
Be choosy
---------
Included in the lab1 directory is a program that computes the
(":math:`\mathsf{m}` choose :math:`\mathsf{k}`") binomial coefficient
.. math::
\mathsf{{m \choose k} = \frac{n!}{k!(n-k)!}}.
The naive implementation
.. code-block:: c++
unsigned long int binomial(unsigned long int n, unsigned long int k)
{
return factorial(n)/factorial(k)/factorial(n-k);
}
seems to work fine for the combinatorics of a small number of items
.. code-block:: console
$ make binomial
$ g++ -o binomial binomial.cpp -O -ansi -pedantic -Wall
$ ./binomial 8
(8 choose 0) = 1
(8 choose 1) = 8
(8 choose 2) = 28
(8 choose 3) = 56
(8 choose 4) = 70
(8 choose 5) = 56
(8 choose 6) = 28
(8 choose 7) = 8
(8 choose 8) = 1
but it fails for larger numbers
.. code-block:: console
$ ./binomial 24 | head -n 10
(24 choose 0) = 1
(24 choose 1) = 1
(24 choose 2) = 0
(24 choose 3) = 0
(24 choose 4) = 0
(24 choose 5) = 0
(24 choose 6) = 2
(24 choose 7) = 5
(24 choose 8) = 12
(24 choose 9) = 22
Convince yourself that this calculational error is caused by integer
overflow. Note that Python circumvents this by handling arbitrarily
large numbers in software (rather than using fixed-bit-width integers in
hardware, trading speed for flexibility).
Write a smart implementation of the binomial coefficient in any or all
of C++, Julia, Python, and Rust based on the identity
.. math::
\mathsf{{m \choose k}}
= \mathsf{\frac{1\cdot 2\cdots n}
{(1\cdot 2 \cdots p)(1\cdot 2 \cdots q)}}
= \mathsf{\frac{(p+1)(p+2)\cdots n}{1\cdot 2\cdots q}},
where :math:`\mathsf{p} = \mathsf{\textsf{max}(k,n-k)}` and :math:`\mathsf{q} = \mathsf{\textsf{min}(k,n-k)}`. You should be
able to reproduce the following terminal session.
.. code-block:: console
$ ./binomial 24 | head -n 10
(24 choose 0) = 1
(24 choose 1) = 24
(24 choose 2) = 276
(24 choose 3) = 2024
(24 choose 4) = 10626
(24 choose 5) = 42504
(24 choose 6) = 134596
(24 choose 7) = 346104
(24 choose 8) = 735471
(24 choose 9) = 1307504
Think about why this works to avoid overflow. Be sure that you can offer
a careful and convincing explanation.