Order of Operations: is the documentation correct?
#1
https://qb64phoenix.com/qb64wiki/index.p...Operations

Basic's Order of Operations :


  1. Exponential and exponential Root calculations including SQR.
  2. Negation (Note that this means that - 3 ^ 2 is treated as -(3 ^ 2) and not as (-3) ^ 2.)
  3. Multiplication, normal Division, INTEGER Division and Remainder(MOD) Division calculations
  4. Addition and Subtraction calculations



Based on testing with QB64, line "3" above is incorrect.

In the screenshot, we see that division takes precedence over MOD.

If the same thing is happening with QB64PE, then the documentation ought to reflect that MOD (and integer division?) ought not be in the same precedence layer.

   
Reply
#2
Code: (Select All)
Sub Set_OrderOfOperations
    'PL sets our priortity level. 1 is highest to 65535 for the lowest.
    'I used a range here so I could add in new priority levels as needed.
    'OName ended up becoming the name of our commands, as I modified things.... Go figure!  LOL!

    'Constants get evaluated first, with a Priority Level of 1
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_PI"
    ReDim _Preserve PL(i): PL(i) = 1
    'I'm not certain where exactly percentages should go.  They kind of seem like a special case to me.  COS10% should be COS.1 I'd think...
    'I'm putting it here for now, and if anyone knows someplace better for it in our order of operations, let me know.
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "%"
    ReDim _Preserve PL(i): PL(i) = 5
    'Then Functions with PL 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_ACOS"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_ASIN"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_ARCSEC"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_ARCCSC"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_ARCCOT"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_SECH"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_CSCH"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_COTH"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "COS"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "SIN"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "TAN"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "LOG"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "EXP"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "ATN"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_D2R"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_D2G"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_R2D"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_R2G"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_G2D"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_G2R"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "ABS"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "SGN"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "INT"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_ROUND"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "FIX"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_SEC"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_CSC"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_COT"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "ASC"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "CHR$"
    ReDim _Preserve PL(i): PL(i) = 10

    'Exponents with PL 20
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "^"
    ReDim _Preserve PL(i): PL(i) = 20
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "SQR"
    ReDim _Preserve PL(i): PL(i) = 20
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "ROOT"
    ReDim _Preserve PL(i): PL(i) = 20
    'Multiplication and Division PL 30
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "*"
    ReDim _Preserve PL(i): PL(i) = 30
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "/"
    ReDim _Preserve PL(i): PL(i) = 30
    'Integer Division PL 40
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "\"
    ReDim _Preserve PL(i): PL(i) = 40
    'MOD PL 50
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "MOD"
    ReDim _Preserve PL(i): PL(i) = 50
    'Addition and Subtraction PL 60
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "+"
    ReDim _Preserve PL(i): PL(i) = 60
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "-"
    ReDim _Preserve PL(i): PL(i) = 60

    'Relational Operators =, >, <, <>, <=, >=  PL 70
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "<>"
    ReDim _Preserve PL(i): PL(i) = 70
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "><" 'These next three are just reversed symbols as an attempt to help process a common typo
    ReDim _Preserve PL(i): PL(i) = 70
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "<="
    ReDim _Preserve PL(i): PL(i) = 70
    i = i + 1: ReDim _Preserve OName(i): OName(i) = ">="
    ReDim _Preserve PL(i): PL(i) = 70
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "=<" 'I personally can never keep these things straight.  Is it < = or = <...
    ReDim _Preserve PL(i): PL(i) = 70
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "=>" 'Who knows, check both!
    ReDim _Preserve PL(i): PL(i) = 70
    i = i + 1: ReDim _Preserve OName(i): OName(i) = ">"
    ReDim _Preserve PL(i): PL(i) = 70
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "<"
    ReDim _Preserve PL(i): PL(i) = 70
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "="
    ReDim _Preserve PL(i): PL(i) = 70
    'Logical Operations PL 80+
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "NOT"
    ReDim _Preserve PL(i): PL(i) = 80
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "AND"
    ReDim _Preserve PL(i): PL(i) = 90
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "OR"
    ReDim _Preserve PL(i): PL(i) = 100
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "XOR"
    ReDim _Preserve PL(i): PL(i) = 110
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "EQV"
    ReDim _Preserve PL(i): PL(i) = 120
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "IMP"
    ReDim _Preserve PL(i): PL(i) = 130

End Sub


From my math evaluator, which is used internally in QB64 to calculate various values for use with CONST.  This gives you the listing of what our extended Order of Operations is, from first to last.  Wink
Reply
#3
(02-14-2023, 03:36 PM)SMcNeill Wrote: From my math evaluator, which is used internally in QB64 to calculate various values for use with CONST.  This gives you the listing of what our extended Order of Operations is, from first to last.  Wink

In your math evaluator, try:

100 mod 17 / 3

When I run the Math evaluator from the IDE, the above shows 0.
Reply
#4
(02-14-2023, 03:45 PM)Ed Davis Wrote:
(02-14-2023, 03:36 PM)SMcNeill Wrote: From my math evaluator, which is used internally in QB64 to calculate various values for use with CONST.  This gives you the listing of what our extended Order of Operations is, from first to last.  Wink

In your math evaluator, try:

100 mod 17 / 3

When I run the Math evaluator from the IDE, the above shows 0.


[Image: image.png]

From this topic: https://staging.qb64phoenix.com/showthread.php?tid=1266 ??

The results I'm getting is a match for how QB64 calculates the output for us.
Reply
#5
Can you show what you get when you run it (100 mod 17 / 3) from the Math Tool in the IDE?
Reply
#6
(02-14-2023, 03:57 PM)Ed Davis Wrote: Can you show what you get when you run it (100 mod 17 / 3) from the Math Tool in the IDE?

I was digging into that.  Something recent (I think/hope) has glitched the internal evaluator.  I've mentioned it to the other devs and we'll sort into it ASAP.  Wink
Reply
#7
(02-14-2023, 03:36 PM)SMcNeill Wrote:
Code: (Select All)
Sub Set_OrderOfOperations
    'PL sets our priortity level. 1 is highest to 65535 for the lowest.
    'I used a range here so I could add in new priority levels as needed.
    'OName ended up becoming the name of our commands, as I modified things.... Go figure!  LOL!

    'Constants get evaluated first, with a Priority Level of 1
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_PI"
    ReDim _Preserve PL(i): PL(i) = 1
    'I'm not certain where exactly percentages should go.  They kind of seem like a special case to me.  COS10% should be COS.1 I'd think...
    'I'm putting it here for now, and if anyone knows someplace better for it in our order of operations, let me know.
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "%"
    ReDim _Preserve PL(i): PL(i) = 5
    'Then Functions with PL 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_ACOS"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_ASIN"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_ARCSEC"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_ARCCSC"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_ARCCOT"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_SECH"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_CSCH"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_COTH"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "COS"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "SIN"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "TAN"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "LOG"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "EXP"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "ATN"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_D2R"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_D2G"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_R2D"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_R2G"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_G2D"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_G2R"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "ABS"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "SGN"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "INT"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_ROUND"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "FIX"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_SEC"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_CSC"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "_COT"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "ASC"
    ReDim _Preserve PL(i): PL(i) = 10
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "CHR$"
    ReDim _Preserve PL(i): PL(i) = 10

    'Exponents with PL 20
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "^"
    ReDim _Preserve PL(i): PL(i) = 20
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "SQR"
    ReDim _Preserve PL(i): PL(i) = 20
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "ROOT"
    ReDim _Preserve PL(i): PL(i) = 20
    'Multiplication and Division PL 30
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "*"
    ReDim _Preserve PL(i): PL(i) = 30
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "/"
    ReDim _Preserve PL(i): PL(i) = 30
    'Integer Division PL 40
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "\"
    ReDim _Preserve PL(i): PL(i) = 40
    'MOD PL 50
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "MOD"
    ReDim _Preserve PL(i): PL(i) = 50
    'Addition and Subtraction PL 60
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "+"
    ReDim _Preserve PL(i): PL(i) = 60
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "-"
    ReDim _Preserve PL(i): PL(i) = 60

    'Relational Operators =, >, <, <>, <=, >=  PL 70
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "<>"
    ReDim _Preserve PL(i): PL(i) = 70
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "><" 'These next three are just reversed symbols as an attempt to help process a common typo
    ReDim _Preserve PL(i): PL(i) = 70
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "<="
    ReDim _Preserve PL(i): PL(i) = 70
    i = i + 1: ReDim _Preserve OName(i): OName(i) = ">="
    ReDim _Preserve PL(i): PL(i) = 70
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "=<" 'I personally can never keep these things straight.  Is it < = or = <...
    ReDim _Preserve PL(i): PL(i) = 70
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "=>" 'Who knows, check both!
    ReDim _Preserve PL(i): PL(i) = 70
    i = i + 1: ReDim _Preserve OName(i): OName(i) = ">"
    ReDim _Preserve PL(i): PL(i) = 70
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "<"
    ReDim _Preserve PL(i): PL(i) = 70
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "="
    ReDim _Preserve PL(i): PL(i) = 70
    'Logical Operations PL 80+
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "NOT"
    ReDim _Preserve PL(i): PL(i) = 80
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "AND"
    ReDim _Preserve PL(i): PL(i) = 90
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "OR"
    ReDim _Preserve PL(i): PL(i) = 100
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "XOR"
    ReDim _Preserve PL(i): PL(i) = 110
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "EQV"
    ReDim _Preserve PL(i): PL(i) = 120
    i = i + 1: ReDim _Preserve OName(i): OName(i) = "IMP"
    ReDim _Preserve PL(i): PL(i) = 130

End Sub


From my math evaluator, which is used internally in QB64 to calculate various values for use with CONST.  This gives you the listing of what our extended Order of Operations is, from first to last.  Wink

Thanks kindly Steve, but that is way too heavy for this kid.

I rely heavily on accurate and consistent documentation when trying to understand the big picture of something.

All it takes is for a teensy-weensy part of that picture to be incorrect/inconsistent, and the whole picture no longer makes sense to me.  And I get seriously annoyed by it.

Documentation is a hard and thankless job, but I hate it when I can't trust what I'm reading and have to double-check it.
Reply
#8
What it breaks down to is that Order of Operation is a lot more complex than you'd imagine.

Functions first
^ SQR
* /
\
Mod
+ -
=, >, <, <>, <=, >=  
NOT
AND
OR
XOR
EQV
IMP
Reply
#9
Looks to me like MOD is rounding 17/3 = 5.6666... up to 6 because 100 mod 5.666 also = 4

Therefore the division is coming before the MOD.
b = b + ...
Reply
#10
As already mentioned, the order in which the individual operators are considered is important.

Different operators at the same level are so executed: the leftmost operation first, the rightmost operation last.

If one want to be absolutely sure that a calculation is carried out in a certain order, then one just put brackets.

(a = 4.000 - a2 = 0.063 - a3 = 2.500)
Code: (Select All)
'Rangfolge von Operatoren - 14. Feb. 2023
'QuickBasic Befehlsverzeichnis 3.2

$Console:Only
Option _Explicit

Dim As Double a, a2, a3

a = 100 Mod 17 / 3
Print Using "###.###"; a

'There is one exception to the normal ranking:
'If an expression has adjacent exponentiation and negation operators,
'then the negation is performed first.
a2 = 4 ^ -2
Print Using "###.###"; a2

'The leftmost operation first, the rightmost operation last.
'According to their order of operations (Rangfolge)
a3 = 3 + 6 / 12 * 3 - 2
Print Using "###.###"; a3

End
Reply




Users browsing this thread: 2 Guest(s)