One standard task for the analytical chemist is to take a sample of some substance and determine its chemical formula -- something like Pb3O4 or NiBr2. The one- and two-letter abbreviations stand for chemical elements (`Pb' is lead, `O' is oxygen, `Ni' is nickel, `Br' is bromine), and the subscript attached to such an abbreviation indicates the number of atoms of that element in each molecule. For instance, a molecule of Pb3O4 contains three lead atoms and four oxygen atoms. If no subscript is present, the molecule contains only one atom of the specified element.
The chemist starts by determining the percentage, by weight, that atoms of each element contribute to the sample. For instance, she might discover that a hundred-gram sample contains 69.9 grams of iron and 30.1 grams of oxygen. This doesn't mean that the atoms in the sample observe the same proportion, though, because each iron atom is much more massive than each oxygen atom. To discover the true proportions, the chemist must divide each percentage by the atomic weight of the element. Atomic weights are usually given in grams per mole -- that is, the mass of a (large) constant number of atoms of the element. The atomic weight of iron is 55.847 grams per mole, while that of oxygen is 15.999 grams per mole. So the sample contains 69.9 / 55.847, or 1.25, moles of iron and 30.1 / 15.9994, or 1.88, moles of oxygen.
Usually, however, you can't make up a molecule from 1.25 or 1.88 atoms of anything -- the number of atoms of each element in each molecule should be an integer. So the remaining problem is to find two small integers that stand in the same ratio as 1.25 to 1.88. In this case, it's pretty easy -- 1.25 / 1.88 is very close to 2/3, so the sample contains two atoms of iron for every three atoms of oxygen, and the formula we're looking for is Fe2O3 (`Fe' is iron). In general, however, the ratio is not as easily guessable.
The program that we'll study today attempts to automate this process. It does all its own input and output and can therefore be run from MzScheme, but you'll initially want to load it into DrScheme so that you can examine, explore, and improve it.
The program that you are to examine and modify is stored in a file called /home/stone/courses/scheme/examples/stoichiometry.ss. Make a copy of this file in your home directory by starting a terminal-emulator window and typing in the command
cp /home/stone/courses/scheme/examples/stoichiometry.ss stoichiometry.ss
Start DrScheme, asking it to load your copy of the program initially:
drscheme stoichiometry.ss &
Read through the program and figure out what each procedure does and how it does it. If you like, you can experiment with each procedure as you come to it. When you click on the Execute button, DrScheme will learn the definitions and set up an interactions window in which you can invoke them however you like.
The program uses four primitive Scheme procedures that we haven't seen before:
numerator and denominator, each of which
takes a rational number as its argument, expresses it as a fraction and
returns the top or bottom integer in the fraction.rationalize, which takes two arguments, both real numbers,
and returns a rational approximation to the first argument. The rational
number is chosen to be as ``simple'' as possible, in the sense of being
expressible as a fraction with the smallest possible numerator and
denominator, provided only that the difference between the approximation
and the first argument is less than or equal to the second argument. (So,
for example, (rationalize (sqrt 2) 1/100) finds the simplest
rational approximation to (sqrt 2) that differs from it by
not more than 1/100.)symbol->string, which takes a symbol as its argument and
returns a string representation of the name of the symbol. Either
upper-case or lower-case letters may be used in the string.
Write the bodies of the prompt-for-element and
mole-equivalent procedures so that they satisfy the
descriptions given in the comments that precede them.
As it stands, stoichiometry.ss contains only definitions. Turn it into a working program by adding one procedure call at the end. Save the resulting program and run it from MzScheme, using the data from the example above. Your interaction should look something like this:
bourbaki% mzscheme -r stoichiometry.ss Give me the symbols for the two elements in your sample and the amounts you found of each one, and I'll determine the chemical formula for the compound. Element: Fe Amount (in grams): 69.9 Element: O Amount (in grams): 30.1 The chemical formula of the sample is Fe2O3.
Use the program to determine the constitution of a sample that contains 8.70 grams of nitrogen (N) and 1.88 grams of hydrogen (H).
Chemists will recognize that this method implemented in this program succeeds only for ionic compounds, since it does not and cannot distinguish such pairs of covalent compounds as NO2 and N2O4, which have the same percentage composition by weight.
Once the ratio between the number of atoms of one element and the number of atoms of the other has been determined by the method implemented here, however, we can distinguish these covalent compounds if we also know the molecular weight of the compound in the sample -- the sum of the atomic weights of the atoms in one molecule. By dividing the molecular weight of the compound by the sum of the atomic weights in the atoms making up the simple ratio, we obtain the number by which we have to multiply the numbers in the simple ratio to get the actual numbers of atoms in the molecule.
For example, suppose the molecular weight of the compound is known to be 46.006. The sum of the atomic weights of one nitrogen atom and two oxygen atoms is 23.003, so the multiplier is 46.006 / 23.003, or 2, and our compound is N2O4.
Adapt the program so that it asks the user for the molecular weight of the compound and uses it to compute the correct formulas for such covalent compounds as well.
This document is available on the World Wide Web as
http://www.cs.grinnell.edu/~stone/courses/scheme/stoichiometry-project.xhtml
created March 6, 2000
last revised March 27, 2000