Math (Order of Operations)

HotShoe

Well-Known Member
Licensed User
Math operations are key to writing programs in any language. In the "I am learning Java" thread in the Chit Chat forum, @wonder posted an example of how he writes code in response to a post of mine and others. His post reminded me how important the order of operations are in math and how much of a difference that order can make to your programs, so this lesson was born.

There is a simple set of rules that exist for math equations, and they work in any language. Those rules are below.

First perform any calculations inside parentheses.
Next perform all multiplications and divisions, working from left to right.
Last, perform all additions and subtractions, working from left to right.

An example is in order so we'll start simple to show how a quick and dirty equation can go horribly wrong. Below is a B4A project that you can run if you'd like, or just follow along as I explain what is happening.

B4X:
#Region  Project Attributes
   #ApplicationLabel: mathtest
   #VersionCode: 1
   #VersionName:
   'SupportedOrientations possible values: unspecified, landscape or portrait.
   #SupportedOrientations: unspecified
   #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
   #FullScreen: False
   #IncludeTitle: True
#End Region

Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'These variables can be accessed from all modules.

End Sub

Sub Globals
   'These global variables will be redeclared each time the activity is created.
   'These variables can only be accessed from this module.

End Sub

Sub Activity_Create(FirstTime As Boolean)
'Do not forget to load the layout file created with the visual designer. For example:
'Activity.LoadLayout("Layout1")
  Dim a, b, x, y As Int
   
  b = 9
  x = 6
  y = 8
   
  a = b + x * y - 5
  Log("a = " & a)
   
  a = b + x * (y - 5)
  Log("a = " & a)
   
  a = 5 * y + x / 12 * 2 - x   
  Log("a = " & a)
   
  a = (5 * y + x) / (12 * 2 - x)
  Log("a = " & a)
   
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

If you run this, or better yet, do it on paper or a calculator, the first equation should equal 52. If we apply the 3 rules above we get:

a = b + x * y - 5 = 52

That is:
6 * 8 = 48 (rule 2)
48 - 5 = 43 (rule 3)
43 + 9 = 52 (rule 3)

We determine the answer this way because of the second rule:

Next perform all multiplications and divisions, working from left to right.

So we start with any multiplication and division and solve those parts of the equation first. Then we go to the 3rd rule

Last, perform all additions and subtractions, working from left to right.

Simple right? What if that is not the answer we expected, or needed? The second equation uses the same variables with the same values, but the answer is completely different. How can this be? It is the same equation, in the same order, with the same values. Except it isn't the same equation.
a = b + x * (y - 5)

It is solved like this:

x * (y - 5) = 18
b + 18 = 27

That is:

(8 - 5) = 3
6 * 3 = 18
9 + 18 = 27

In this equation we are using parentheses to force the order of operation to be different than the first equation. The numbers are all the same, but the order that each stanza of the equation is solved is different.

The second equation uses all 3 of our rules:

First perform any calculations inside parentheses.
Next perform all multiplications and divisions, working from left to right.
Last, perform all additions and subtractions, working from left to right.

As you can see, the order of operation makes all the difference in getting to the answer that you expect. Lets look at the 3rd and 4th set of equations.

a = 5 * y + x / 12 * 2 - x
and
a = (5 * y + x) / (12 * 2 - x)

Again, each has the same variables in the same order and with the same values in each position, and again, the answers are vastly different because of the order of operation applied to each.

The first is solved using rules 2 and 3 in that order:

5 * 8 = 40
6 / 12 = 0.5
0.5 * 2 = 1 (This is because most compilers do math in doubles or floats)

then solve the addition and subtraction using rule 3

1 - 6 = -5
40 + -5 = 35

The 4th example uses all 3 rules to force the order of operation to be different.

a = (5 * y + x) / (x - 12 * 2)

First we solve the equations inside of the parentheses according to rule 1, starting with rule 2 and then rule 3

First parenthesis
5 * 8 = 40
40 + 6 = 46

Second parenthesis

12 * 2 = 24
24 - 6 = 18

Then the second rule applied to the sum of the answers from both stanzas

46 / 18 = 2 (actually 2.555555555555556 but the variable a is an integer)

You can (and will) also use parentheses inside of parentheses to further define the order that you want calculations made. It is common to see complex equations written like this to ensure that each element has the value that is intended. Just use the rules in order to solve long or complex equations. ALWAYS start by solving the parenthesis stanza first while applying the other rules inside those stanzas.

So why should you bother to learn this stuff? Well, you don't have to unless you want your calculations to be correct. Programming in any language is math intensive. Even simple apps have to do math to position views on the screen or figure out how many items were sold. As apps get more complex, so does the math. No one knows that better than game programmers or graphics applications designers.

Knowing what to expect when you write your equations, and how the compiler will handle each part is very important. Would you do business with a bank that didn't know how to calculate your account balance, or a construction company that couldn't calculate the correct measurements for your new room addition?

I hope this has answered more questions than it has raised. There are binary operators in various languages like AND, OR, NAND, NOR, XOR, etc that also follow rule 2 for the most part, but most will rarely if ever need to deal with those.

The important thing is to train yourself to think like a machine while you look at your code. Once you get to the point where you know how the compiler goes through your code, your apps will not only work correctly, but the code will be much cleaner and easier to maintain.

--- Jem
 

wonder

Expert
Licensed User
This is a great addition to th e B4X tutorials / lessons! Congrats on your post, @HotShoe!! :)
In order to show how important is the use of parenthesis, I would like to add a practical example.

Let's say you're creating an artillery type game, such as Angry Birds and you want to calculate how far will your projectile reach.
Within a few seconds of googling we're able to find all we need (https://en.wikipedia.org/wiki/Range_of_a_projectile), including the magic formula.

250px-ProjectileRange.jpg
b1c5647476c66437d2183de53f091d77.png

For this example we'll assume you're working with degrees instead of radians.

Unfortunately, you can't just copy-paste this image, you'll have to enter this formula manually into your code.
It may seem daunting, be believe me, if you do it step-by-step, everything will turn-out just fine.

Literally, "Too long; didn't read". Said whenever a nerd makes a post that is too long to bother reading.
Untitled_2.png

Step 1: Translate the variables
From the same wiki page, we can copy-paste the variable definitions into our code as comments.
B4X:
'g:   the gravitational acceleration—usually taken to be 9.81 m/s2 (32 f/s2) near the Earth's surface
'θ:   the angle at which the projectile is launched
'v:   the velocity at which the projectile is launched
'y0:  the initial height of the projectile
'd:   the total horizontal distance travelled by the projectile
...and replace them with our own as necessary. For example:
B4X:
'World.Gravity:         the gravitational acceleration
'Projectile.Angle:      the angle at which the projectile is launched
'Projectile.iVelocity:  the velocity at which the projectile is launched
'Cannon.PosY:           the initial height of the projectile
'Projectile.Range:      the total horizontal distance traveled by the projectile
Step 2: Translate the formula
At first glance, you can easily see the formula can be broken into two parts.
The first one becomes:
((Projectile.iVelocity * CosD(Projectile.Angle)) / World.Gravity)
The second one can also be broken into two parts:
(Projectile.iVelocity * SinD(Projectile.Angle))
and
Sqrt((Power(Projectile.iVelocity, 2) * Power(SinD(Projectile.Angle), 2)) + (2 * (World.Gravity * Cannon.PosY)))
Step 3: Add it to your code
Just like a puzzle, it's time to put the pieces together:
Projectile.Range = ((Projectile.iVelocity * CosD(Projectile.Angle)) / World.Gravity) * ((Projectile.iVelocity * SinD(Projectile.Angle)) + Sqrt((Power(Projectile.iVelocity, 2) * Power(SinD(Projectile.Angle), 2)) + (2 * (World.Gravity * Cannon.PosY))))
B4X:
Projectile.Range = ((Projectile.iVelocity * CosD(Projectile.Angle)) / World.Gravity) * ((Projectile.iVelocity * SinD(Projectile.Angle)) + Sqrt((Power(Projectile.iVelocity, 2) * Power(SinD(Projectile.Angle), 2)) + (2 * (World.Gravity * Cannon.PosY))))
It looks like a mess, doesn't it? So let's use the "_" character to break the formula into several lines.
B4X:
'World.Gravity: the gravitational acceleration
'Projectile.Angle: the angle at which the projectile is launched
'Projectile.iVelocity: the velocity at which the projectile is launched
'Cannon.PosY: the initial height of the projectile
'Projectile.Range: the total horizontal distance traveled by the projectile

Projectile.Range = _
      ((Projectile.iVelocity * CosD(Projectile.Angle)) / World.Gravity) _
    * ((Projectile.iVelocity * SinD(Projectile.Angle)) _
    + Sqrt((Power(Projectile.iVelocity, 2) * Power(SinD(Projectile.Angle), 2)) _
    + (2 * (World.Gravity * Cannon.PosY))))
Et voilá! It took me almost 20 years to finally realize that math is fun, especially when you can see it in action through your code. I hope I didn't scare anyone away. :)
 
Last edited:

HotShoe

Well-Known Member
Licensed User
In order to show how important is the use of parenthesis, I would like to add a practical example.

Excellent practical example @wonder! Your post in the other forum inspired me in the first place.

--- Jem
 
Top