Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Note: by 'complex' math I mean an equation with many steps involved and a wide mix of operators.

A programmer should know the order that operators are evaluated in an equation. However it can be a royal pain to look at an equation such as:

result = value_1 + value_2 * value_1 + value_3 / value_4 % value_5; 

One option is to write out the equation in multiple steps such as:

part1 = value_2 * value_1;
part1 += value_1;

part2 = value_4 % value_5;
part2 = value_3 / part2;

result = part1 + part2;

Another option is to format the original equation with parenthesis such as:

result = (value_1 + (value_2 * value_1)) + (value_3 / (value_4 % value_5)); 

When dealing with complex math in code, how do you typically format it to maximize readability?

share|improve this question

6 Answers 6

up vote 9 down vote accepted

You're right -- every programmer should indeed know order of operations. If you come across code like your example:

result = value_1 + value_2 * value_1 + value_3 / value_4 % value_5;

and you're not sure whether % takes precedence over /, then you should absolutely look it up. Every smart programmer keeps at least one reliable reference manual for their language of choice within arm's reach. Learning (or re-learning) details like this is the way that you gain experience. If you take these opportunities every time they present themselves you'll soon find that you never have to look anything up because you know it cold.

The deeper problem with the example above is that it doesn't convey the programmer's intent. You should be able to read that line and know exactly what it does, but there's no way to know if it does what the author intended. Even if you wrote it, you probably won't remember exactly what you were thinking at the time. Well-named variables, white space, parentheses, and functions are all tools that you can use to help communicate what you expect your code to do and why. There's no sense in choosing to use one of those options; use whichever combination seems clear. Instead of:

float w = (m1 + m2 + m3) * a * d;

write:

float totalMass = mass1 + mass2 + mass3;
float force = totalMass * acceleration;
float work = force * displacement;
share|improve this answer
1  
I didn't say knowing your order of operations is a "royal pain". I said looking at something like the example was a pain because it is more or less just a blob with no formatting. –  Glenn Nelson Aug 27 '11 at 18:02
    
@GlennNelson, sorry, I misread that. I've edited the post. However, if you know the order of operations inside-out, the operators themselves start to look like separators, and the line looks less like "just a blob." –  Caleb Aug 27 '11 at 19:12
2  
+1 for the point about making your intent clear for future maintainers. –  Peter Taylor Aug 27 '11 at 20:34
1  
You can know the precedence of operators too well - or at least over-use that knowledge. You may find that that this kind of thing looks less like "just a blob", but outside of the most obvious precedence relationships, I certainly find lines like this a readability issue. Among other issues, some of us switch languages more than others, and the operator set and precedence/associativity varies from one language to another. People should know the language they're using, of course, but coding isn't an "I know more than you" contest - adding the extra parens or whatever is often a good thing. –  Steve314 Aug 28 '11 at 21:34
1  
@Caleb - BUT you also have to be sure that whoever wrote the code, and whoever will subsequently maintain it - knew the order and didn't make a mistake. Brackets, like politeness, cost nothing ;-) –  Martin Beckett Aug 29 '11 at 0:58

Generally, write for programmer first, for computer second. Compilers are aggressive optimizer these days (which sucks if you are trying to implement Kahan summation), so take liberty at introducing temp variables that make sense. Mixing more than two of [*, /, and % and ** (exp)] in one line is a bad idea, IMO - too many opportunities for bugs and it slows down whoever is trying to read this code. If you can use FP, then you have many tools to control the complexity. I would go through SICP book and videos that you can dl via torrent.

Just as with regular code, try to avoid 'formatting' - rather split things up into small functions and/or temp variables that make sense. The SICP book does complex stuff, and yet the code is never long. If you have to leave a long line on occasion, just do what makes sense. Again, a good lesson from LISP would be to try to align parenthesis from one line to the next.

In other languages see these examples:

http://en.wikipedia.org/wiki/Kahan_summation_algorithm

http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance

The math is somewhat complex, and yet the code is not. It is all about controlling the complexity. Hopefully these two examples can set you in the right direction.

share|improve this answer

I use a mix:

  • I heavily use temp variables in particular for results that are used multiple times (this is a bit of a micro optimization but it soothes my mind)

  • and when it's still not really clear I use parenthesis and play with the spacing of it so priorities are clear at a glance and similar stuff lines up nicely even when not all variables are the same length:

    result = (val_1   + value_2*val_1   ) + 
             (value_3 -   val_4%value_5 ); 
    
share|improve this answer

Your question is about maximizing readability of an equation. I suggest the following:

A. Put in a comment or in your documentation with the equation clearly stated in its original mathematical form. Complex calculations should have a reference outside the code for people to build test cases and to understand where do the equations come form.

B. Splitting the equation enhances debugging of parts of the equation. It also allows you to catch overflows and similar problems that could occur. For example:

x= ((b*b) + Sqrt(b*b-(4*a*c))) / -1*2*a may lead to an error if b*b-(4*a*c) is negative or if a is zero. you can split this expression to report each case separately with a different error message.

If you have several expression, there may be a sub expression that repeats in several equations. It would be more efficient to calculate that expression separately to improve performance.

C. If you split an expression, make sure the intermediate expressions are assigned to the correct variable type. For example,

int j=Sqrt(b*b-(4*a*c)) is not good.

D. Writing long un-split equations may be not readable and makes tracking braces difficutl

So, I suggest you split with care.

share|improve this answer

I think readability is not such a big issue in such cases. Using parenthesis is one option. Other thing one can do is to use the multi-line statements like the one used by ratchet. Also, you use use commenting in all the programming language.

Therefore, just concentrate more on the computing algorithm and equations. Rest are very minor things to worry about

share|improve this answer

In Algol-like languages, I would do it like this:

result := value_1 +
          value_2 * value_1 +
          (value_3 / value_4) % value_5;

Note that I assume an arbitrary precedence rule for / over %. I would use explicit parentheses in any language for this.

Lisp has standard formatting guidelines for such things, and it is completely explicit, e.g.:

(let ((result (+ value-1
                 (* value-2 value-1)
                 (mod (/ value-3 value-4)
                      value-5))))
  (do-something-with result))
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.