Author Topic: Double Check on order of operations  (Read 4287 times)

0 Members and 1 Guest are viewing this topic.

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Double Check on order of operations
« on: January 22, 2022, 02:43:56 pm »
So in our order of operations, are * and /(and \) on the same level or does one take precedence over the other?
for instance if we have;

Scale%% = 3
Xloc% = 450 - 16 * 11 \ 2 * Scale%%

Would everything after the `-` evaluate from left to right or would(should) both multiplications go then the division? Since both Multiply and Divide are secondary operations(following Exponents and SQR).
I know the `-` goes last, but was curious if this would run straight or if I have to waste extra time and characters adding () around parts of it.(my testing says the latter, but wanted to make sure my testing was correct)

funny how you can spend years coding and never run across something then out of the blue...
Granted after becoming radioactive I only have a half-life!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Double Check on order of operations
« Reply #1 on: January 22, 2022, 02:50:48 pm »
I think it's the same between two + and/or - operators, left to right = right to left.

eg /2 is same as *.5

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Double Check on order of operations
« Reply #2 on: January 22, 2022, 03:00:09 pm »
If I remember correctly, division occurs before integer division.  Let me Check my math evaluator and I'll confirm/deny my suspicions for you.

Edit:

   'Multiplication and Division PL 30
    i = i + 1: OName(i) = "*": PL(i) = 30
    i = i + 1: OName(i) = "/": PL(i) = 30
    'Integer Division PL 40
    i = i + 1: OName(i) = "\": PL(i) = 40


Yep.  Integer Division occurs AFTER multiplication and division.

2 \ 1 * 2 is done as 2 \ (1 * 2), not (2 \ 1) * 2.  The answer is 1; not 4.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline George McGinn

  • Global Moderator
  • Forum Regular
  • Posts: 210
    • View Profile
    • Resume
Re: Double Check on order of operations
« Reply #3 on: January 22, 2022, 03:02:59 pm »
This is how it is supposed to work:

Quote
The PEMDAS rules that state the order in which the operations in an expression should be solved, are:
1. Parentheses - They take precedence over all other operators. The first step is to solve all the operations within the parentheses. Work out all groupings from inside to out. (Whatever is in parentheses is a grouping)
2. Exponents - Work out all the exponential expressions.
3. Multiplication and Division - Next, moving from left to right, multiply and/or divide whichever comes first.
4. Addition and Subtraction - Lastly, moving from left to right, add and/or subtract whichever comes first.

So in the code provided, * and \ (/) are processed left to right in the order they appear in the calculation (same goes for addition/subtraction).

It seems that QB64 isn't doing that, otherwise the answer should be 186 instead of 421

The code below breaks Cobalt's formula down the way it is supposed to be calculated:

Code: QB64: [Select]
  1. Scale%% = 3
  2. Xloc% = 450 - 16 * 11 \ 2 * Scale%%
  3.  
  4. PRINT Xloc%
  5.  
  6. x = 16 * 11
  7. x = x \ 2
  8. x = x * Scale%%
  9. x = 450 - x
____________________________________________________________________
George McGinn
Theoretical/Applied Computer Scientist
Member: IEEE, IEEE Computer Society
Technical Council on Software Engineering
IEEE Standards Association
American Association for the Advancement of Science (AAAS)

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Double Check on order of operations
« Reply #4 on: January 22, 2022, 03:06:58 pm »
Yeah Integer division would make a difference because of which number it's rounding.

Once again the age old advice is: To be sure of the order of operations, put the numbers in ()'s.

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: Double Check on order of operations
« Reply #5 on: January 22, 2022, 03:08:02 pm »
I think it's the same between two + and/or - operators, left to right = right to left.

eg /2 is same as *.5

what made me question was I did this;

Scale%% = 0
Xloc% = 450 - 16 * 11 \ 2 * Scale%%

and received a Division by Zero error. which seems to suggest that * goes before \(/) in QB64
Granted after becoming radioactive I only have a half-life!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Double Check on order of operations
« Reply #6 on: January 22, 2022, 03:10:12 pm »
Quote
So in the code provided, * and \ (/) are processed left to right in the order they appear in the calculation (same goes for addition/subtraction).

Rules of operation are quite a bit more complex than that.

For instance, - takes place before multiplication and division....  At least it does if it's negation!

Multiplication and Division occur BEFORE integer division...

NOT is before/after orders of operation based on it's left/right positioning...

Programming order of operation is more complicated than youthink.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Double Check on order of operations
« Reply #7 on: January 22, 2022, 03:10:36 pm »
what made me question was I did this;

Scale%% = 0
Xloc% = 450 - 16 * 11 \ 2 * Scale%%

and received a Division by Zero error. which seems to suggest that * goes before \(/) in QB64

Steve caught the main difference of Integer division, that's not the same as normal division.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Double Check on order of operations
« Reply #8 on: January 22, 2022, 03:27:12 pm »
Steve caught the main difference of Integer division, that's not the same as normal division.

As long as we're talking about this here, may as well mention MOD comes after all multiplication, division, and integer division.

* and / are processed.
\ comes next.
MOD comes last.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline luke

  • Administrator
  • Seasoned Forum Regular
  • Posts: 324
    • View Profile
Re: Double Check on order of operations
« Reply #9 on: January 26, 2022, 10:06:31 pm »
The full list, from highest to lowest precedence, is:
  • Exponentiation (^)
  • Negation (-)
  • Division (/), Multiplication (*)
  • Integer Division (\)
  • MOD
  • Subtraction(-), Addition(+)
  • Equality (=), Ordering (<, <=, >, >=)
  • NOT
  • AND
  • OR
  • XOR
  • EQV
  • IMP
Operators on the same line are evaluated left to right, or inside out in the case of the unary operators NOT and negation. In practice, this means:
  • NOT 2 + 3 is NOT (2 + 3) because + has higher precedence and so is evaluated first
  • - 2 ^ 3 = -(2 ^ 3) because ^ has higher precedence and so is evaluated first

Apparently this full list isn't in the wiki anywhere; it probably should be.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Double Check on order of operations
« Reply #10 on: January 26, 2022, 11:21:24 pm »
To add a note to Luke's list here:  NOT is a weird beast with regards to order of operations, as it resolves itself depending on what's to the left and right of it.

For instance:  3 * NOT 1 - 1

We do multiplication before NOT.  Right?

Not in this case!!


NOT is a special beast which evaluates itself as if it was in parenthesis from the point directly before it to every point after it but before any other binary operators.   (If you guys can wrap your minds around what I'm trying to say here.) 

Let me illustrate with a few examples:

3 * NOT 1 -1 evaluates as 3 * (NOT 1 - 1).
3 * NOT 1 -1 AND 2 evaluates as 3 * (NOT 1 -1) AND 2.
1 ^ 4 + 3 * NOT 1 - 1 * 2 ^ 4 OR 5 evaluates as 1 ^ 4 + 3 * (NOT 1 - 1 * 2 ^ 4) OR 5.

NOT is actually resolved FIRST, but only up to the point where it's interrupted by a binary operator such as AND, OR, XOR.

NOT's a complex little bugger to wrap your head around, when it comes to order of precedence, and the best way I've learned to process it is to encase it in parenthesis as I illustrated above with any evaluator program.  Start parenthesis right before the NOT, end it at the end of the formula or whenever AND, OR, XOR, EQV, IMP appears in the code.

Try it yourself for a bit, if you want to see how odd it is.  Start with a simple little 3 * NOT 1 - 1.

If multiplication went first, wouldn't we resolve it as:
(3 * NOT 1) - 1
(3 * -2) - 1
-6 -1
-7

That's NOT the answer however.   Instead, it's resolved as I mentioned:
3 * (NOT 1 - 1)
3 * (NOT 0)
3 * (-1)
-3

A special case which one has to juggle around if they're going to make an evaluator, or else you're NOT going to get the correct answer.  :P


https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline George McGinn

  • Global Moderator
  • Forum Regular
  • Posts: 210
    • View Profile
    • Resume
Re: Double Check on order of operations
« Reply #11 on: January 30, 2022, 03:28:25 pm »
@luke

In all of math, Integer Division is not treated any different than division or multiplication.

The same goes for MOD.  (See: https://mathworld.wolfram.com/Division.html

Integer Division returns the Quotient only from a division, where MOD returns only the remainder. All are considered division and is supposed to be performed left to right.

All three (four including MOD) should be treated on the same level. Hence, with a mixture of \ and /, all are computed left to right.

For example:  5 / 10.5 \ 5 * 6

The correct answer is 15, yet QB64 returns 0. 0 is incorrect.

Check the following results from Wolfram Alpha:
https://www.wolframalpha.com/input/?i=5+%2F+Quotient%2810.5%2C+5%29++*+6

What is the reason why Integer Division comes after division and multiplication?

The full list, from highest to lowest precedence, is:
  • Exponentiation (^)
  • Negation (-)
  • Division (/), Multiplication (*)
  • Integer Division (\)
  • MOD
  • Subtraction(-), Addition(+)
  • Equality (=), Ordering (<, <=, >, >=)
  • NOT
  • AND
  • OR
  • XOR
  • EQV
  • IMP
Operators on the same line are evaluated left to right, or inside out in the case of the unary operators NOT and negation. In practice, this means:
  • NOT 2 + 3 is NOT (2 + 3) because + has higher precedence and so is evaluated first
  • - 2 ^ 3 = -(2 ^ 3) because ^ has higher precedence and so is evaluated first

Apparently this full list isn't in the wiki anywhere; it probably should be.
____________________________________________________________________
George McGinn
Theoretical/Applied Computer Scientist
Member: IEEE, IEEE Computer Society
Technical Council on Software Engineering
IEEE Standards Association
American Association for the Advancement of Science (AAAS)

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Double Check on order of operations
« Reply #12 on: January 30, 2022, 04:35:06 pm »
What is the reason why Integer Division comes after division and multiplication?

Because we follow the same set of Order of Operations that previous versions of BASIC followed.  We don't invent these rules off the top of our heads, just to spite "real math", you know!  :P

Look back on an old QBasic tutorial and see how it distributes the order of operations:



https://jpsor.ucoz.com/publ/1-1-0-8

        The table below shows the priority of the operation. The highest priority is what comes first.
 
1.       Exponent
2.       Multiplication, Division
3.       Integer Division
4.       Modular (remainder after division)
5.       Addition, Subtraction



And, from an older version of BASIC -- GW Basic:

http://www.antonis.de/qbebooks/gwbasman/chapter%206.html

The following are the arithmetic operators recognized by GW-BASIC. They appear in order of precedence.

Operator   Operation
^   Exponentiation
-   Negation
*   Multiplication
/   Floating-point Division
+   Addition
-   Subtraction

6.4.1.1 Integer Division and Modulus Arithmetic
Two additional arithmetic operators are available: integer division and modulus arithmetic.

In the order of occurrence within GW-BASIC, the integer division will be performed just after floating-point division.

In the order of occurrence within GW-BASIC, modulus arithmetic follows integer division.



So, "Why do we do it like this?"

Because it's the order in which these things have always been done in BASIC -- Wolfram be damned! :P
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Double Check on order of operations
« Reply #13 on: January 30, 2022, 05:05:03 pm »
Also note, QB64 isn't the only modern language to use the same rules of operation.  Compare us to the most recent version of Visual Basic:  https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/operators/operator-precedence#:~:text=Operator%20Precedence%20in%20Visual%20Basic%201%20Precedence%20Rules.,an%20expression%20to%20be%20evaluated%20before%20others.%20

Exponentiation (^)
Unary identity and negation (+, –)
Multiplication and floating-point division (*, /)
Integer division (\)
Modular arithmetic (Mod)
Addition and subtraction (+, –)
String concatenation (&)
Arithmetic bit shift (<<, >>)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline George McGinn

  • Global Moderator
  • Forum Regular
  • Posts: 210
    • View Profile
    • Resume
Re: Double Check on order of operations
« Reply #14 on: January 30, 2022, 05:41:35 pm »
Other "modern" languages, like C/C++, FORTRAN, and even COBOL processes order of operations the way it's supposed to work (See https://en.cppreference.com/w/c/language/operator_precedence for how C/C++ does it).

I bet this is an old feature of the original BASIC.

I think that for QB64 to work the way many other languages work, maybe it needs to change, or provide a compiler directive to tell it to perform order of operations the way most other languages do it. It would improve QB64.

I know I can break up a formula so that it does the math properly, but why? I should be able to process a formula in a straight-line form properly.
____________________________________________________________________
George McGinn
Theoretical/Applied Computer Scientist
Member: IEEE, IEEE Computer Society
Technical Council on Software Engineering
IEEE Standards Association
American Association for the Advancement of Science (AAAS)