On computation and codes¶
Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.
—B.W. Kernighan & P.J. Plauger in The Elements of Programming Style.
Before we start discussing modelling and implementing the different algorithms and methods, let us briefly list a few general issues on design, programming, computing and codes. The remarks below do not depend on the programming language.
Well-written programs: Desirable properties¶
Independent of the chosen programming language, there are several matters that should be considered. It is impossible to write an exhaustive checklist, but the purpose of the short lists below is to bring some of the important issues to the reader’s attention. In all programming, one should be careful and pay attention to detail, and remember debug, debug, and debug.
Portability: Codes should be written in such a way that they are portable, i.e., they must work correctly on different computer architectures
Parallelizability: A good code should be parallelizable. Here, we will not focus on that issue, though.
Readability: A good code should include comments.
Simplicity: The purpose is to solve problems, not to write the most beautiful code.
Programming languages¶
There are only two kinds of languages: the ones people complain about and the ones nobody uses.
—Bjarne Stroustrup, The C++ Programming Language
There are many, many programming languages. There is no ultimate language, but one has to choose the language based on pragmatic arguments. However, Python has become a very popular language for a great number of tasks as well as scientific computing, and C/C++ has become the most common general purpose language. For web-based solutions, javascript is extremely common.
A few additional details for efficient programming¶
In addition to the above design issues, here are a few often overlooked practical issues
Summations: One can minimize roundoff errors if summations are performed in the order of increasing magnitude (add smaller numbers first).
Avoid mixing of types: Do not add floating point numbers and integers. Instead, use a type conversion (functions such as REAL
in Fortran) when performing such an operation. REAL(i)
converts an integer i into a floating point number and it can then be used in operations with other floating point numbers. Although Python does not have type declarations, this issue still matters: For example, consider the difference between 1/2 and 1.0/2.0.
Memory access: Make sure you access computer memory in the most efficient way. For example, in the case nested loops, the first index runs fastest in Fortran, whereas in C/C++ and Python it is the last one. This can make a huge difference in performance.