Qalculate / libqalculate

Qalculate! library and CLI
https://qalculate.github.io/
GNU General Public License v2.0
1.73k stars 142 forks source link

Order of Operations bug, or what? #193

Open Vahtera opened 4 years ago

Vahtera commented 4 years ago

Let's take the "viral" expression that's going through all of social media - 6/2(1+2). The answer to that is, of course, 9. (Those who say 1, update your OoO to post-1917).

However, if you input that to Qalculate, you get 1 as a result? Qalculate somehow uses 1917-notation when deciding what to do. Why is that?

Both "6/2(1+2)" and "6/2x where x=1+2" will give a result of 1 and the expression that is calculated displays as "6/(2 (1+2))" or "6/(2 x) where x = 1+2)" both of which are wrong. Qalculate adds brackets where no brackets are defined.

If I want to use brackets on the equation, shouldn't I be required to input them in the first place - like "6/(2(1+2))" - and not have Qalculate add them when I didn't want them?

I feel like this is quite a serious bug and will easily lead to wrong answers if one is not really, really careful.

hanna-kn commented 4 years ago

There is no "correct" way to interpret the expression, which is why Qalculate always shows how each expression is interpreted and offers a configuration option which controls the handling implicit multiplication.

Different calculators handles implicit multiplication in different ways. My old Casio fx-4500p returns 1. Google returns 9 for 6/2(1+2), but 6/(2*pi)=0.955 for 6/2pi.

The default mode calculates implicit multiplication before explicit multiplication and division, but also takes into account whitespace (e.g. 6/2 (1+2)=(6/2)*(1/2)). Which mode for handling implicit multiplication that should be the default is of course open for discussion.

Arguably the most correct way of handling ambiguous implicit multiplication is to throw an error (as maxima, sagemath, matlab, etc. do). Anyone who is careful should never mix division and implicit multiplication.

Vahtera commented 4 years ago

There is no "correct" way to interpret the expression I humbly beg to differ. There is. If there are no brackets, the program should not "assume" there are, and insert them into the equation.

I expect this with any other program I use, why should a calculator be different? Using whitespace as a marker in order of operations is weird to me. Why should 1/2(2+3) be any different from 1/2 (2+3)? And weirder still, why should 1/2(2+3) give a different result from 1/2(2+3)? Both are mathematically identical. Same thing with variables: "1/2x where x = 1+2" gives a different result than "1/2x where x = 1+2" which is just plain wrong. Again, both of those are mathematically identical.

Again, in my humble opinion, a program should never "assume" what the operator means, and work exactly with what it is given. If one wants to include the whole equation after the "/", one should use parenthesis if the input method in question doesn't allow "textbook" mode input (meaning you can literally write the expression under a long line and not just use "/".

When using just one line of input, a calculator should not assume implicit anything, in my opinion.

I agree with the error though. If the program in question cannot figure out what the user wants, the correct way is to throw an exception and tell the user that they've made an error or and ambiguous statement and should specify which they mean.

Though, again, there is nothing ambiguous to me in 6/2(1+2). If I wanted 6/(2(1+2)), I'd write 6/(2(1+2)) and not 6/2(1+2).

It's of course your program and you may do as you please. To me it is just highly questionable for a (scientific) program to assume anything.

hanna-kn commented 4 years ago

I humbly beg to differ. There is. If there are no brackets, the program should not "assume" there are, and insert them into the equation.

One might just as well say that, if there is no multiplication sign, the program should not assume there is and insert it into the equation. It is actually highly questionable for a scientific program to allow implicit multiplication at all (and neither expressions such as 100+5%=105).

Your of course entitled to your opinion, but it would be better if you could recognize that there are different traditions regarding the handling of implicit multiplication.

set parse 2 (or qalc -s "parse 2", or Mode->Parsing Mode->Conventional Parsing in the GUI) will fix this for you. You also have the option to fork libqalculate and change the default mode (if you are not able to come up with more convincing arguments).

I will add a warning informing the user that the expression is ambiguous.

Vahtera commented 4 years ago

One might just as well say that, if there is no multiplication sign, the program should not assume there is and insert it into the equation.

I would agree, if it wasn't a mathematical practice that has been going on for years and years. 2x means 2x and 2(1+2) means 2(1+2), that's just established way of doing things. That's not even assuming anything, it just IS that. There is no other way to interpret "3x" than "3 times x". It's not ambiguous. It's just how it's done.

I'm a bit iffy with 100+5%. I agree that it's not a scientific way of doing it and would be totally okay if a program would not recognize that at all - for the longest time they didn't. However, again, there is no ambiguity in that. If the equation is simply "100+5%" there are no "other ways" to interpret that. The question then is only. "does the program support this feature that may or may not be mathematically correct, but is really useful and easy for users". You cannot confuse the equation with anything else.

I don't understand the different traditions though. Math is not something that has different ways of interpretation regarding where you life or what books you have read. Math is math. There is no traditions. There are no "regional variants". Math works like math works. There is no "other way" to handle things. There WAS, like I said. Pre-1917 it was customary to use 1/1+2 == 1/(1+2). But that NOT used anymore currently. That is the OLD, deprecated way of solving equations. It's not a regional or philosophical variant. It's a rule of how things are done.

I admit I'm not an expert at this, so if you have some better sources than me, that show math has variants of how it's done, please let me know. I would be interested to read on how that is even possible.

But, I'm 100% okay with the warning. The default will be what it will, but if there is the possibility of ambiguity, the program should display this to the user in some way. A warning is a perfectly applicable way of doing it. In my opinion it would be enough if on the side/under the interpreted equation there would be a (red?) text like : "Warning: Current equation is ambiguous, please use brackets or refine equation." (or something like that.)

vvs- commented 4 years ago

Excuse me for intervening, this is indeed interesting to see so different opinions on such a trivial subject. And I just can't help but add my two cents into the picture.

This application is not a system for doing mathematics, this is just a calculator after all. It has to give users a choice to get what they already used to expect from other calculators. And it's not purely mathematical calculator either as it has preference to automatically convert between different physical units. And if you actually take this into account then an expression like 1m is ambiguous as it might mean either implicit multiplication or metric unit as well.

Though, I could agree that what Qalculate! project really is might not be obvious. It grew to get some properties of CAS but it has no ambition to become one. Once I even took it for granted that it should eventually become an interactive theorem proving system, but that was only my own mistake.

Vahtera commented 4 years ago

an expression like 1m is ambiguous as it might mean either implicit multiplication or metric unit as well. Not really, since the only allowed variables are x, y and z if I'm not wrong? (well, and n).

Though, I could agree that what Qalculate! project really is might not be obvious. It grew to get some properties of CAS but it has no ambition to become one.

It doesn't? That's really a shame, because it could potentially be one of the very best. If nothing else, qalc is pretty much the only console-based calculator that is actually worth using. I actually found Qalculate! because I was looking for a console-solution, but then I liked it enough that I switched everything to it.

qalc is one of the only - if not THE only console-based calculator that can do equations with multiple other equations as "source". (like, "x-y where 2x=3 and y=4") That's simply not possible with any other calculator program I've found. And Qalculate! made that easy to do with GUI also.

Oh well, my bad then. I thought Q! really had intentions of growing up to be a CAS.

vvs- commented 4 years ago

Not really, since the only allowed variables are x, y and z if I'm not wrong? (well, and n).

No, as in any programming language you can use any name. In fact there is predefined ans variable and x, y, z are just another such examples.

BTW look at APL family of programming languages where there is no OoO. Another notorious example should be Lisp where parenthesis are everywhere.

Oh well, my bad then. I thought Q! really had intentions of growing up to be a CAS.

That's only for Hanna to decide, but I think she already spoke her mind.

BTW, Lyx and Texmacs offer good formula editors for CAS.

hanna-kn commented 4 years ago

WolframAlpha, which otherwise treats implicit the same explicit multiplication, interprets 5J/2m as 5J/2*m.

I suggest the you read the answers to the Quora question: https://www.quora.com/Does-6-2-1-2-equal-1-or-9.

This application is not a system for doing mathematics, this is just a calculator after all.

As I wrote before, in advanced mathematical systems implicit multiplication is (often) simply not allowed. Order of operations with implicit multiplication is mainly an issue for less advanced calculators.

Oh well, my bad then. I thought Q! really had intentions of growing up to be a CAS.

My intentions is that Qalculate should be and include everything (including the kitchen sink)... I try to implement everything users ask for, but some advanced functionality is beyond my abilities (or requires to much time and effort) and some might be implemented in odd ways. The main priority is however calculations involving units and physical constants.

Qalculate should provide adequate CAS functionality for less advanced users that do not need all the functionality of complicated math packages. I think that at some point it might not be feasible to combine advanced CAS functionality with a simple interface and other features, or be wise to duplicate the efforts of other projects (it might be a better idea to implement a more user-friendly interface for one of those).

Not really, since the only allowed variables are x, y and z if I'm not wrong? (well, and n).

Users can add as many variables as they like, or use backslash and quotation marks (e.g. \a-"var2" where 2\a=3 and "var2"=4).

Vahtera commented 4 years ago

set parse 2 (or qalc -s "parse 2", or Mode->Parsing Mode->Conventional Parsing in the GUI) will fix this for you. You also have the option to fork libqalculate and change the default mode (if you are not able to come up with more convincing arguments).

Thank you! This is really close to what I looked for. Sorry for missing it earlier. It makes Qalculate! much better for me! In fact, this might've been the single thing that I needed.

But, should this also affect the equation in the original question? With parsing mode set to "Adaptive parsing" or "Parse implicit multiplication first" BOTH provide the same result with "6/2(1+2)". Shouldn't the second parse mode interpret that as "6/2*(1/2)" and then go from there? Both modes do the exact same with both of those examples. (This is with the GUI/Windows 3.9.0 version. I didn't test qalc yet. I'll test as soon.)

EDIT: It DOES work on qalc! qalc '6/2(1+2)' and qalc -s "parse 2" '6/2(1+2)' interpret the equation in different way and provide a different result.. so there's a bug in the GTK+ version... I'll go put that in the proper place then.

As far as I'm concerned, I'm happy with this (because the -s "parse 2" worked with qalc) and I have no further issue with this. In my opinion this should be the default to avoid potential errors, and misunderstandings. But that's just that, my opinion and is worth what it's worth - one user's opinion.

hanna-kn commented 4 years ago

But, should this also affect the equation in the original question? With parsing mode set to "Adaptive parsing" or "Parse implicit multiplication first" BOTH provide the same result with "6/2(1+2)". Shouldn't the second parse mode interpret that as "6/2*(1/2)" and then go from there? Both modes do the exact same with both of those examples. (This is with the GUI/Windows 3.9.0 version. I didn't test qalc yet. I'll test as soon.)

"Parse implicit multiplication first" does of course mean that implicit multiplication is calculated first (e.g. 2(1+2)), before explicit multiplication and division. The third option (beginning at zero in qalc), "Conventional Parsing", does not differentiate between implicit and explicit multiplication and returns the result you expect. The first default mode takes into account whitespace and other factors (e.g. 5ft 2in is interpreted as 5ft+2in). (Perhaps I should change the behaviour in this mode for implicit multiplication with parentheses (e.g. 6/2(1+2)=6/2*(1+2), but 6/2x=6/(2x)), but this might make it even more confusing.)

vvs- commented 4 years ago

My intentions is that Qalculate should be and include everything (including the kitchen sink)...

That's actually the source of all the confusion. People like to use as little tools as possible for all their tasks and will complain if they don't meet their expectations. It's in human nature. That's why Emacs became what some ironically call "operating system". Better approach is a Unix toolbox paradigm: many small components for small tasks and good combinators for them all.

But that's software philosophy.