Sunday, 23 February 2014

Week READING WEEK

\( ' .')/

Week 6 Name scopes

One of the interesting things that came up in lecture this month was the Python built-in name scope statements, global and nonlocal,and closely related, globals() and locals(). global should be relatively familiar to most. It allows you to define a variable inside a function that can be used outside of the function. nonlocal is a neat extention that, functionally, is almost the reverse of global, and is most prevalent when you define a function inside a function. It allows you to reference a variable on the nested function that you defined on the outside function. If you have g() inside f(), and you define x = 5 inside f(), typing "nonlocal x" inside g() allows you access to the x you defined in f to do whatever you want with it.
The closely related locals() and globals() are functions themselves, and you can call them whenever to check the current locally or globally defined names. They both return a dictionary of variable names and their values.
dir() is also related. Called without an argument, it gives you the currently defined names in a list. Called with an argument, and it will give you all the methods and attributes that the argument has.
dir() does not discriminate between attributes and methods, and I was curious as to how to find simply all the methods that a class has, and it turns out to be possible using the built-in module inspect. To find all methods in a class, you type the following: inspect.getmembers(your_object, predicate=ismethod). "ismethod" is not the only keyword argument you can type. There is also ismodule, isclass, isfunction, and many others that you can find on the official Python documentation page.

Sunday, 9 February 2014

Week 5 Floating Point Precision continued

Last week we saw that Python sometimes deal with decimals strangely. Here is another example you can try in your shell.

>>> 1.1 + 2.2
3.3000000000000003

The pinch is that Python only stores around 16 significant figures. Any numbers after that is up to chance. We say that standard deviation on the a value x is 10e-16 * x. This is the error you would see in the format datum = value +/- error. These errors propagate to the rules of statistics, and is the reason why floating point precision is so important. The math is out of the scope for this course, but an example of error propagation is the following:
given x = A +/- e1, y = B +/- e2, then x + y is given by x + y = A + B +/- sqrt(e1^2 + e2^2).
Strangely enough, the error of the sum do not simply add like e1 + e2, but is given by the Pythagorean formula. Let us also define the percentage error as error_value / datum_value. An error of 5 on a value of 100 thus has a 5% error. What happens to the percentage error when you add two of the same value with errors?

(100 +/- 5) + (100 +/- 5) = (100 + 100) +/- (sqrt(5^2 + 5^2)) = 200 +/- 7

7/200 = 3.5%. The percentage error has gone down! If we had simply multiplied our value by two, we would've gotten 2*(100 +/- 5) = 200 +/- 10, giving the same 10% error. The reason for this reduction in error from the previous example is due to the fact that, despite the values being the same, we were actually adding two distinct datum values. And the rules of statistics says that the more data you have, the better. These are some of the things you might encounter doing any large scale or lengthy computations on a computer.

Sunday, 2 February 2014

Week 4 - Floating point precision

Outside of the realm of graphic interfaces or databases, a major field in cs is the science of computation. This is your typical "number cruncher" that calculates pi to the 3 billionth digit. Inevitably, big numbers are involved. Or sometimes, extremely small numbers. But of course, large or small, any number can be concisely represented in scientific notation. 30000 and 0.00003 in scientific notation only differ by a sign change: 3e5 vs 3e-5. But what if you want to store 1/3 in a variable? 1/3 = 0.333333... You can't type infinite digits can you? But being an eager cs student you immediately look for a workaround. Okay, I'll just type x = 1./3. And typing 3 * x in the shell gives me 1.0. Tada, I made my program store infinite decimals.

Sadly, that is not that case. Here's an example to try. Type in the shell 1e-20 + 1 - 1. From inspection we see trivially that the answer is 1e-20, yet our program doesn't give us that answer. It gave us 0.0! How can this be? Next, try 1e-20 + (1 - 1). What do you see? Next, try lowering the number 20 until you see "proper" results.

>>> 1e-15 + 1 - 1
1.1102230246251565e-15

That certainly is strange isn't it?