Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

An annoyance with spreadsheets that deterred me from ever using them in teaching is that they've perpetuated a arithmetic order-of-precedence bug. ("Bug" in the sense that it contradicts long-standing mathematical convention.) If you type

    -3^2
in a cell and press ENTER, the spreadsheet tell you it's "9". It should be "-9"; in math, exponentiation has precedence over unary minus, so you square 3, then negate the result. For instance, if you tell students to graph "y = -x^2", they should draw a parabola opening downward.

I don't have a recent copy of Excel to check this in, but this was the case in the '97 version. I just tried it in the current LibreOffice calc, and it returns "9". My guess is that one of the early spreadsheets messed up the order of precedence, and everybody after copied it for compatibility.

On the other hand, I just tried maxima and python and they both give "-9".

I wonder if this particular problem afflicts people who copy formulas from (say) math books into spreadsheets.



This issue seems like partly an artifact of the invented binary operator ^. In math exponents are superscripts and there's no binary operator- it's part of the term. But for text on computers, binary operators ended up being fabricated for the things you couldn't represent directly. The caret is common and was the first one to appear, but doubled multiplication signs is another one. Traditionally, binary operators have lower precedence than unary operators since the unary minus is considered part of the term, so the exponent turning into an operator mucks things up if it's still implemented to adhere to that logic.

You sort of see the same issue with division. The forward slash is a completely invented binary operator since the actual division symbol was often not present- and let's be real nobody uses the binary division operator when writing formulae. It's supposed to represent the dividing line in a fraction, similar to how division is usually represented in a formula as a fraction of two other expressions. It's got lower precedence than anything in either term- but, if you just replace the dividing line with a forward slash to input the formula into a computer, you'll get incorrect results, because it's replacing what is part of a complete term (the division line) with a new binary operator inserted between sets of terms, which is now subject to precedence rules.


I suspect it's more likely an artifact of how the number is lexed. `-3^2` probably gets lexed into Number(-3), Operator(^), Number(2), which results in the aforementioned precedence issues. The reason for parsing the operator with the number is that it makes it easier to handle the case where you just write a negative number as a literal value into a cell.

Source: I've written an Excel clone before. I don't believe it has the same bug, but if it does, that will be how it's crept in.

EDIT: looking at some of the descriptions of the bug, it seems like it happens when handling variables (i.e. cell references) as well, which makes it seem like a pure precedence issue and not a parsing issue. So I've got no idea, presumably someone simply messed up the precedence order.


It's almost certainly a precedence issue. It's much easier to consider that unary operators have precedence over binary operators, and just learn the precedence rules for each class, rather than a global precedence rule. Plus, there's no conflict with math notation, as there is no exponentiation operator in math.


In my country we teach the same rules in math class. Blaming it on “unary vs binary” was a stretch. Next you’re going to blame it on the lexer for producing the -3 as a single term instead of two. (Which WOULD explain something, but… fix it?!)

In my country we use a horizontal line with a dot above and below to indicate in-line division in lower grades. Exactly like the computer /.

It’s not like there was no precedent here.


I also learned the line with a dot above and below in my country, the USA. But that was a very long time ago, math teaching has changed immeasurably since my time.

In Unicode it's U+00F7: https://www.compart.com/en/unicode/U+00F7


In the C language, -a*b parses as (-a)*b, but c-a*b parses as c-(a*b).

Unary minus has a higher precedence than binary operators.

You don't notice because the semantics allows the sign to move around, unlike with exponentiation.

But when we throw in edge cases involved in undefined behavior, oops!

  0 - INT_MIN/2 // fine: parses as 0 - (INT_MIN / 2)

  -INT_MIN/2    // not okay: parses as (-INT_MIN) / 2
The INT_MIN value need not have an additive inverse because of a quirk in two's complement.


> The INT_MIN value need not have an additive inverse because of a quirk in two's complement.

For comparison, in Java, these 3 expressions each yield Integer.MIN_VALUE (i.e. -2147483648):

    -Integer.MIN_VALUE
    Integer.MIN_VALUE * -1
    Integer.MIN_VALUE / -1
I have to admit I expected all 3 to throw.

edit On reflection I shouldn't have expected that, I recall reading John Regehr's blog post on the downsides of how Java defaults to wrapping behaviour: https://blog.regehr.org/archives/1401


This is probably the most overly pedantic, nitpicky reason for not using a program I've ever heard.

I'm aware that there are two different conventions on this issue, so I just use parentheses to get the behavior I want.

But, growing up, as the top math student in my class, it never occurred to me that somebody out there wants -3^2 to equal -9, I thought it was just a weird quirk in some calculators/programs. How would you read that expression aloud? I think of it as "negative three squared" so that's why (-3)^2 makes sense to me. Do you say "the negative of three squared"?

In 8th grade, I remember being instructed to type such an expression into the calculator to observe how it does something contrary to what we expect it to. From that moment on, I thought, "Huh, guess you have to use parentheses." It certainly wasn't cause enough to throw out my calculator, let alone tell others not to use it, just because I prefer a slightly different precedence convention.


> This is probably the most overly pedantic, nitpicky reason for not using a program I've ever heard.

If you found learning math easy, you're fortunate. But lots of people find learning math difficult and frustrating, and things which might not have bothered you can be big deals for those folks. If I used a program in teaching which has a convention about basic arithmetic operations that is the opposite of the convention that mathematicians use, it is one more source of confusion and frustration for people.

Student: "You said that -3² was -9, but Excel says it's 9."

Me: "Well, mathematicians use a different convention than spreadsheets."

Student: "So which one should I use on a test? Can we use both?"

Me: "Since this is a math class, you should use -9, not 9."

Student: "How am I supposed to remember that? This is why I hate math ..."

Everyone will weigh costs and benefits differently. There is plenty of good math software out there like Mathematica, R, Geogebra, or maxima. Spreadsheets didn't seem to offer much, and there was this arithmetic convention thing that I knew would be an issue.

I'm sorry if you find it pedantic and nitpicky. I always tried to minimize unnecessary causes for upset, because there were difficulties enough learning math without my adding to them. If you saw people getting extremely angry or in tears because they "didn't get it", I think you'd understand. Math is really hard for some people.


I think we should agree that standard notation is too ambigious and switch to reverse polish notation:

  3 2 ^ -     -9
  3 - 2 ^      9
No way to misinterpret that!


Except 3 - 2 ^ makes it hard to express 3 2 - ^ without accidentally subtracting, so in this case a unary negation sign needs to be a different symbol!


I dug out my HP 50g over the weekend to play with, and conveniently…

Sigh. I understand why we commonly enter math on basically a teletype-with-ASCII, and I don’t have an urge to go all APL, but for a while we were so close to a future where we could’ve had separate negation or multiplication or exponentiation symbols that might’ve removed so much room for error. I mean, that little calculator and its predecessors were popular and widely used by the same people who brought us things like Unicode and the space cadet keyboard. If only one of them had said, gee, it sure would be handy to have a +- key on the keyboard the person in the next cubicle is designing as I have on the calculator on my desk!

But nope, Everything Is ASCII won and here we are. At least programming languages are starting to support Unicode identifier names, which has its own issues but is excellent for non-Latin alphabet users who want to write code in their own tongue. It seems like a reasonably short hop from there to giving operators their own unambiguous names. I can imagine a near-distant future where a linter says “you typed -3. Did you mean ⁻3?”, to the chagrin of programmers still entering their code on teletypes.


It would be nice if OSs defaulted numeric keypad / * and - to Unicode ÷, ×, −. I never use them even when I do use the digits. That would solve the more glaring typewriter legacies. Then you'd just have the apostrophe/single-quote as the last remaining unification.


I'm not convinced. I was brought up with the middle dot for multiplication (and × reserved for cross products, I suppose?) and according to Wikipedia, the

> ISO 80000-2 standard for mathematical notation recommends only the solidus / or "fraction bar" for division, or the "colon" : for ratios; it says that the ÷ sign "should not be used" for division

I think these things are way less standardised even on paper than you believe.


That was kind of my point. We somewhat settled on an ASCII representation of many symbols, and that space is so small that lots of them have multiple meanings you have to infer. There was a brief window where we could’ve taken a different path and used different symbols for different things. Alas, we didn’t.

I don’t contend we should change things today. I do think if I were personally writing a new programming language from scratch today, I’d likely use different Unicode symbols for different operators, and the accompanying language server would nudge people to use them.


Everyone learnt -3^2=-9 in middle school… it is a very clear implementation mistake


"minus (pause) three squared"


I had a discussion on one of the Nim boards because Nim does the same, i.e. Writing -2^2=4 but 0-2^2=-4 because Nim treats the first as the unary - which takes precedence over exponentiation. I realise that you can argue how it is technically correct (and interestingly several of the people I was talking with couldn't even get my point), but I still argue it's incredibly unintuitive for anyone coming from an regular engineering/science background who wants to do regular work. I would almost argue will exclude it to be used by many due to this.


You're right that violating established mathematical convention can be a deal-killer for some kinds of adoption.

A few years ago I was reading the docs for a new programming language, thinking it might be useful in teaching. The docs were well-written and in a beautifully produced book. I got to the chapter on trig functions and discovered that they'd decided to make angles increase clockwise. And there was a graph of the sine function, with the graph below the x-axis from 0 to 180 degrees. And I sadly put the well-written beautifully-produced book on the shelf and haven't looked at it since.

I can see why people would think "angles increase clockwise" is more natural than the existing convention ("angles increase counterclockwise") - it's the way clocks do it, right? Yeah, it's just convention, but when the established convention has been around for at least a century or two and there are libraries full of books and papers which use it, "more natural" still isn't good enough reason to break with it. And it really wasn't necessary to do that for their project.

I'm sure people who do software can think of lots of conventions which may even suck but will never be replaced.


The Godot game engine has its 2d graphics origin at the top-left of the screen, with the positive Y axis pointed down. Having clockwise trig functions is a natural consequence of that.

I think it's a fairly common setup for all 2D graphics software.


I don't think I've ever seen a graphical system of any kind that didn't have 0,0 at the top-left corner of the monitor or viewport either, with positive x going right and positive y going down.

I actually didn't even think about it until now. Now it's going to bug me. God damnit. :V


Somewhat related, bitmap files (.bmp) store the image lines in bottom-to-top order, effectively putting (0,0) at the bottom-left.

It's the only image format I've ever seen that does that -- everyone else stores lines in top-to-bottom order, consistent with putting (0,0) at the top-left.


What do bitmap and excel have in common? :D


E.g. OpenGL normalized device coordinates have x=0,y=0 at screen center, with top left being x=-1,y=1. It's easier to reason with in many cases.


> I don't think I've ever seen a graphical system of any kind that didn't have 0,0 at the top-left corner of the monitor or viewport either, with positive x going right and positive y going down.

Is that because the electron beam in cathode ray tubes scanned from top left to bottom right?


OS/2's Presentation Manager had 0,0 at the bottom-left corner of the monitor.


I just checked and Adobe Illustrator does the same.

I think it’s interesting that actually, they didnt change the rotation definition (from X+ toward Y+), but because it’s a visible change from their inversion of the plane, people believe they did.


"more natural" is a good reason any time since otherwise you get to perpetuate these bad conventions for all the future generations to suffer.


What is "more natural" is a matter of opinion, and opinion will differ.

But even if there's a lot of agreement that an existing convention could stand improvement, that doesn't by itself make it "a good reason any time" for throwing out the existing convention.

What is a "convention"? It's something followed by a large "installed base". So changing a convention means a large cost will be incurred in changing up.

Who should decide whether the benefits of changing outweigh the costs? Someone has to pay for it, and simple fairness suggests that the people who will bear the costs of changing up should have the largest say.

The point is that just because someone thinks something new is better doesn't mean that old should be thrown out. And if you ignore that installed base, the change just doesn't happen.

We tried in the U.S. to switch over to metric years ago. Many of us think it would have made sense, but many more people didn't agree and it didn't happen.

It would be easier computationally if there were 100 degrees in a circle rather than 360. But the 360-installed-base is too large and the costs of changing are judged to be too great, so we're stuck with 360.

You're absolutely right, though, that suggestions for change should always get a fair hearing, and people who believe in them should go ahead and see if enough other people will sign on.


> I got to the chapter on trig functions and discovered that they'd decided to make angles increase clockwise.

That is an established mathematical convention, called "bearing". https://en.wikipedia.org/wiki/Bearing_(navigation)

> And there was a graph of the sine function, with the graph below the x-axis from 0 to 180 degrees.

But that definitely isn't a convention anywhere; bearing 0 has sine 1.

There isn't really one mathematical convention on "angles". There's a fairly strong one on angles that are named theta, but in a math class it's normal to orient phi in whatever way makes sense to you. As you trace a sphere, do you want phi to represent the angle between (1) the radius ending in your point and (2) the xy plane, as that angle varies from negative pi/2 to pi/2? Do you want it to represent the angle between (1) the radius ending in your point and (2) the positive z axis, as that angle varies from 0 to pi? That's your call. An increase in the angle just means it's getting wider; what direction that requires the angle to grow in depends on how you defined the angle and which of its sides is moving.


Regardless of relative directions around circles, the sine and cosine between 0° and 90° can be described unambiguously in terms of ratios between side lengths of right triangles. You could decide to define the functions differently, but then they'd no longer be the sine and cosine, they'd be something else. The whole point of having these two named functions is that they're a common ground, independent of whatever idiosyncratic angle measurements are useful for a given problem.


> Regardless of relative directions around circles, the sine and cosine between 0° and 90° can be described unambiguously in terms of ratios between side lengths of right triangles.

That's true, if there are no angles greater than 90° or less than 0°, as is the case in a non-pathological right triangle. In this case, as ratios of nonnegative lengths, all trig functions are always nonnegative.

If you want to include angles outside those bounds, then you care about what exactly occurs where, and while you can unambiguously define angles between 0 and 90 to have all positive trig functions, you can also unambiguously define them to have negative sines and tangents. Fundamentally what's happening is that you're defining certain line segments to have negative length instead of positive length. Which line segments should have negative length isn't a question about angles.

> You can decide to define the functions differently, but then they'd no longer be the sine and cosine, they'd be something else.

Only in a sense much stricter than what people generally use. Sine and cosine themselves are hard to distinguish - you can also call them sine (x) and sine (x - 270). Some people might argue that the sine of (x - 270) is still a sine.

> In general, the two functions can be described by their differential equations

If you do that, you'll completely lose the information about where sine is positive and where it's negative. You can apply any phase shift you want (as long as you apply it to both functions) and their differential equations will look exactly the same.


> If you want to include angles outside those bounds, then you care about what exactly occurs where, and while you can unambiguously define angles between 0 and 90 to have all positive trig functions, you can also unambiguously define them to have negative sines and tangents.

You could define trig functions differently, but then you'd need a separate pair of unnamed functions to express "the ratios of unsigned side lengths of a right triangle in terms of its unsigned interior angles". It's the same reason we don't count "-1 apple, -2 apples, -3 apples, ...". Or why horizonal and vertical lines usually fall on the x-axis and y-axis instead of the (1/√2,1/√2)-axis and (-1/√2,1/√2)-axis. We optimize for the common case.

> If you do that, you'll completely lose the information about where sine is positive and where it's negative. You can apply any phase shift you want (as long as you apply it to both functions) and their differential equations will look exactly the same.

What do you mean? "sin(0) = 0, cos(0) = 1, and for all x, sin'(x) = cos(x), cos'(x) = -sin(x)" is perfectly unambiguous. If you changed the initial conditions, you'd get another pair of functions, but then they'd no longer be the sine and cosine, they'd be some other linear combination. And for that, refer to what I said about the x-axis and y-axis: better to take the stupid simple (0,1) solution and build more complex ones from there.


> What do you mean? "sin(0) = 0, cos(0) = 1, and for all x, sin'(x) = cos(x), cos'(x) = -sin(x)" is perfectly unambiguous.

It's pretty straightforward. "sin(0) = 0" is not a differential equation. Any phase shift applied to sine and cosine will produce exactly the same set of differential equations that apply to sine and cosine; you can rename the shifted functions "sine" and "cosine" and you'll be fine.


> That is an established mathematical convention, called "bearing".

Bearing is a nautical convention not a mathematical one.

I have worked on boat computer systems and can assure you that all the angles were in radians going in the proper direction while beatings were separate always shown in degrees and clockwise.


As someone else noted, "bearing" isn't a mathematical convention. To be clear, when I say "mathematical convention" I mean what mathematicians do and teach. But I didn't know about "bearing" in navigation so thanks for mentioning that.

> There isn't really one mathematical convention on "angles".

There is for angles in the plane, which are the angles I was discussing. In every math course from trig where people first encounter angles in the plane they increase as you go counterclockwise. This is true in trig, precalc, calculus, ... You will not find a math textbook in which plane angles increase clockwise. I think that counts as a convention.

That convention determines the graph of the sine function, because sin theta is defined in trig courses as the y-coordinate of the point where the ray from the origin determining the angle intersects the unit circle. So (e.g.) if 45 degrees means 45 degrees clockwise, that ray is below the x-axis, and the y-coordinate of the intersection is negative -- and hence, sin 45 degrees would be negative.

If angles increase clockwise from the positive x-axis, then sin 45 degrees will be negative. And if sine 45 degrees is negative, then angles are increasing clockwise from the positive x-axis. And any mathematician would tell you that sine 45 degree is 1/sqrt(2), not -1/sqrt(2).

> ... in a math class it's normal to orient phi in whatever way makes sense to you.

You're correct that there are two prevailing conventions for the angle phi in spherical coordinates. Mathematicians measure phi downward from the positive z-axis, so it takes values from 0 to 180 degrees. (Actually, it's sort of like "bearing" that you mentioned.) Physicists measure phi upward from the x-y plane, so it can take values from -90 to 90 degrees. It does cause some confusion in teaching Calc 3, because students also taking a physics or astronomy course may be seeing two conventions for phi. However, in 3 dimensions (spherical coordinates) there's no natural "clockwise" or "counterclockwise".

But there is a convention for measuring phi in math classes -- it's the one I described above. Check any calculus book. Our colleagues in physics don't like it, but oh well. :-)


There's no regular engineering convention about the ^ exponentiation operator, because there is no exponentiation operator in regular or engineering math notation. The superscript used for exponentiation doesn't need a precedence level, it has a natural grouping behvaior.

This is most visible in the fact that you never need parentheses around an exponent expression in math notation, but you need them a lot in programming notation. They are just different notations.

Consider in math notation:

   2+2
  3    + 5
Programming notation:

  3^(2+2)+5
Completely different notations in a much more fundamental way than how they treat unary minus.


It's insane to me that you'd throw away a whole language, toolchain, ecosystem, and community, just because you disagree with the caret operator not taking precedence over a unary minus. Do they not have parentheses on the keyboards where you're from?


The exponent operator is just short for the POWER function in Excel. So from that perspective it is the correct behaviour I think even if it is mathematical incorrect.


I recall reading that this was easier to implement in memory constrained machines running Excel back then, and now can't be changed for compatibility.

It has bitten me when I computed the pdf of a standard normal in Excel, invoking exp(-A1^2), say.

Someone made a website (in 2003, it's a bit out of date) tracking this issue:

http://www.macnauchtan.com/pub/precedence.html


But of course it can be changed, you can make it configurable even if you decide the default should continue be this silly mistake "for compatibility"


There's no "mistake", the current way makes much more sense in programming notation. It's far better that -3^2 is consistent with -3+2. The caret notation for exponentiation is anyway completely different, and works very differently in terms of precedence from using super scripts in math.


That's a mistake in every statement: Excel isn't programming, so programming notation isn't even relevant

There is also no difference in the caret notation vs superscript, its upward pointing form literally meant to signify SUPERscript

It's far better that

0-3^2

-3^2

are consistent, consistency between exponent and addition makes little sense since by universal convention they have different priorities, so you'd not expect any "consistency" there Also your -3+2 example is meaningless since its output is the same as

-((+3)+2)

so there is no inconsistency with

-9

And no, ^ doesn't universally work differently vs superscript, just in some poorly designed apps


Excel formulae are absolutely a form of computation, or programming.

While the caret is meant to symbolize superscript, it is nevertheless a completely different notation for exponentiation.

I don't see why 0-3^2 and -3^2 need to be consistent necessarily. Sign change and subtraction are different operations, so they can have different relationships with other operators.

If + worked like you want ^ to work, then -3+2 would equal -5, instead of the more common -1.

^ does work differently from superscript in all apps. The way you write "three to the power two plus two" is completely different.


Abacus is a form of computation, doesn't make it programming.

> While the caret is meant to symbolize superscript, it is nevertheless a completely different notation for exponentiation.

Wait, do you believe slash / to be a completely different notation with different rules for division?

Also, it's not completely different, I've already explained that its form points to the same participle - RAISing base to the power, exactly the same as superscript. It's just that input/typesetting on computers is very primitive, so you can't really use superscript conveniently, otherwise it's semantically the same, so having different rules for the same meaning makes no sense

> I don't see why 0-3^2 and -3^2 need to be consistent necessarily

ok, if you fail to see this basic similarity but somehow think -3+2 is identical, don't have anything else to say here

> If + worked like you want ^ to work, then -3+2 would equal -5, instead of the more common -1.

Why would I ever want addition to work the same as exponeiation??? That's your weird wish for them to behave the same, I respect the math precedence of operators.

> ^ doesw differently from superscript in all apps

that's not true, https://www.wolframalpha.com/input?i=-3%5E2

Many calculators / calculator apps also behave the same


In Wolfram alpha as well, ^ is a different notation than superscripts: https://www.wolframalpha.com/input?i=-3%5E2%2B2

And of course / is completely different from fractions too. Math notation is two-dimensional, and requires relatively few parentheses. Computer notation is uni-dimensional and requires parentheses all over the place.

This is how math notation looks like, try to write this in C/Excel/Wolfram Alpha without parens:

      2 + 2
    -3      + 4
   _____________ = 17
      2 + 3


> try to write this ... without parens:

Why? This extra condition doesn't help you, and why your link shows nothing, it behaves exactly as I'd expect, ^ is identical to superscript, you're just making an implicit mistake of thinking +2 is somehow covered by ^ and would be part of the superscript, but it wouldn't, that's a different source of ambiguity

What would help is an example where parens aren't needed, but nonetheless slash would mean something else vs horizontal line, like in the original example

That's how you show semantic "completely different"


The math notation doesn't need parens. The computer notation needs parens. This alone is simple obvious proof that they are different notations, at least in my understanding of what a notation is.


-3^2 in the math notation doesn't need parens only because of operator precedence.

The fact that the computer ^ requires parens in more cases like -3^(2+2) is irrelevant for this and doesn't allow you justifying different precedence rules (and your downgrading from "completely different" to "different" isn't a proof, just "tautology". Hey, they also look different, so they are different!)


I don't have a horse in this seemingly extremely important race, but Excel absolutely is programming


It is configurable - with brackets.


You confuse configuration with data entry


But it's 9!

Check it: https://www.mathplanet.com/education/pre-algebra/explore-and....

"You also have to pay attention to the signs when you multiply and divide. There are two simple rules to remember: When you multiply a negative number by a positive number then the product is always negative. When you multiply two negative numbers or two positive numbers then the product is always positive."

So basically you have -3x-3 and result is 9.


No - in a subtle way, you're assuming that the unary minus has precedence, when the point is that it doesn't.

You're right that "thing^2" means "thing times thing", but in "-3^2", what is it that is being squared? To write it, as you did, as "(-3) x (-3)", assumes that in "-3^2" the thing being squared is "-3". But that in turn assumes that the unary minus is done before the square. By the standard mathematical convention, in "-3^2" the thing being squared is "3". So you do "3 * 3", then you negate the result and get "-9".


Interesting. In our high school math class when -3^2 was hand written it was ok to interpret it as (-3)^2. But maybe that could have been because spacing would be used as some informal parentheses.


Leaving "-3²" to be "interpreted" according to context is not a good idea. Mathematical notation should be unambiguous and context-free as much as possible, not "do what I mean". A computation involving "-3²" will be right or wrong depending on what it means; that shouldn't depend on who is reading it or under what circumstances.

Not to unduly slight your teacher, but it could be they weren't sure about what "-3²" means. Everyone who teaches has gaps in their knowledge -- I sure did. :-)


Precedence rules are mostly a formalization of the underlying basic convention that the operations whose terms are written closer together are done first.


Mostly to make polynomials easy.

But if we’re doing math mostly on computers, we should adopt rules that make writing on computers easy — not pedantically insist typing code follow the rules of handwriting polynomials.


It was the same for me. The question seems to be whether "-3" here represents the operation "negate" or the number "negative 3". If it's the latter, then -3^2 is (-3)^2.


Thanks. I had no idea. Seems counterintuitive at first, but it makes sense, since ’-3’ is '0 - 3'.


This is a good way to think of it. It would be very confusing if “0 - 3^2” and “0 + (-3^2)” should mean different things.


But what about (0-3)^2?

You said that “-3” = “0-3”.

So we have “-3^2” is “(0-3)^2” is 9. Agreeing with -3^2 = 9.

You’re performing a sleight of hand when you define “-3” to be “0-3”, but move the parenthesis to get your second equation. You have to insert your definition as a single term inside parenthesis — you can’t simply remove them to change association (as you have done). That’s against the rules.

So if you think “-3” is “0-3”, then you should agree the answer is 9.


> (0-3)^2?

It’s entirely unambiguous due to the parenthesis.

I don’t think the rest of your argument actually makes sense.

There is no sleight of hand required. The original argument is entirely related to having unary minus and binary minus which are different operators conceptually have similar precedence as being less surprising.


My point is that you can’t define “-3” as “0-3” to make it work: you’re assuming exactly what’s being debated (via sleight of hand) when you insert the terms with brackets in the way you do rather than the way I do.

When you try to swap in the unary operator without that to make it “less surprising”, you get 9.

Precisely what you said was wrong about the unwary operator (in Excel).


But no one is defining -3 as (0-3). You are entirely missing the point. I am going to quote myself again:

> The original argument is entirely related to having unary minus and binary minus which are different operators conceptually have similar precedence as being less surprising.

And no, you don’t get 9 when you swap the unary operator. That’s the whole point and why it’s surprising that Excel did reverse the precedence for implementation easiness.


> You said that “-3” = “0-3”.

No, I didn’t.


Isn't this treating 3 as something that can be analyzed from -3? Like -3 is the union of 3 and the (-), and not something onto itself. Ought it to be the case that negative is more than just a sign? Like, I think 3 should be ontologically distinct from -3, even if the addition of 3 and -3 = 0. Idk, I don't have a reason for this, it feels right for some reason.


You are mistaking the notation for the object.

There is indeed two ontologically different elements 3 and (-3) in Z. The question is however purely about what is the meaning of the ambiguous without precedence rules representation -3^2.

Note that it gets more complicated quickly if you want to keep thinking about it in that mathematicians often consider ontologically different but equivalent operations as the same when it’s irrelevant to what they are doing or the results trivially extend to both case. See for example 3-3 and 3+(-3).


I mean, all equations are true if all terms are set to equal zero, so the term itself must have some sort of ontological distinction.


-3^2 is not a standard mathematical convention. -3² is, but that is completely different in many other ways.


https://www.wolframalpha.com/input?i=-3%5E2

https://en.wikipedia.org/wiki/Order_of_operations

Parentheses, Exponentiation, Multiplication, Division, Addition, Subtraction

-3^2 would then be correctly parsed as -(3^2) which is -9.

Parsing it as (-3)^2 would require the addition of parentheses.

This gets to the special case of the unary minus sign... which the Wikipedia article specifically calls out.

    Special cases

    Unary minus sign

    There are differing conventions concerning the unary operation '−' (usually pronounced "minus"). In written or printed mathematics, the expression −3² is interpreted to mean −(3²) = −9.

    In some applications and programming languages, notably Microsoft Excel, PlanMaker (and other spreadsheet applications) and the programming language bc, unary operations have a higher priority than binary operations, that is, the unary minus has higher precedence than exponentiation, so in those languages −3² will be interpreted as (−3)² = 9. This does not apply to the binary minus operation '−'; for example in Microsoft Excel while the formulas =-2^2, =-(2)^2 and =0+-2^2 return 4, the formulas =0-2^2 and =-(2^2) return −4.
(edit)

Digging into this a little bit more...

https://www.gnu.org/software/bc/manual/html_mono/bc.html#TOC...

    The expression precedence is as follows: (lowest to highest)

    || operator, left associative
    && operator, left associative
    ! operator, nonassociative
    Relational operators, left associative
    Assignment operator, right associative
    + and - operators, left associative
    *, / and % operators, left associative
    ^ operator, right associative
    unary - operator, nonassociative
    ++ and -- operators, nonassociative

    This precedence was chosen so that POSIX compliant bc programs will run correctly. This will cause the use of the relational and logical operators to have some unusual behavior when used with assignment expressions. Consider the expression:
    ...
This brings us to the POSIX specification for bc https://pubs.opengroup.org/onlinepubs/9699919799.2018edition...

This also shows the unary - having higher precedence than ^.

https://github.com/gavinhoward/bc/blob/master/manuals/develo...

    This document is meant for the day when I (Gavin D. Howard) get hit by a bus. In other words, it's meant to make the bus factor a non-issue.

    This document is supposed to contain all of the knowledge necessary to develop bc and dc.

    In addition, this document is meant to add to the oral tradition of software engineering, as described by Bryan Cantrill.
... now, it would be interesting if gavinhoward could clarify some of the design thoughts there (and I absolutely love the oral tradition talk).


Precedence is a property of notation and operators, not a property of operations. The ^ notation for exponentiation is fundamentally different from the common superscript notation, and so it is only natural that it has different precedence rule. The biggest difference is in how exponent expressions are handled, of course: in math notation, the entire expression is written in superscript and no parantheses are needed; in computer notation, you always need parantheses around the exponent expression.


Gavin Howard here.

There really isn't a design choice to be made. POSIX requires unary negation to have higher precedence.

The only precedence change (I can remember) from GNU bc is that I changed the not operator to have the same precedence as negation. This was so all unary operators had the same precedence, which leads to more predictable parsing and behavior.


The question that I'm curious about is "why does POSIX require unary negation to have a higher precedence?"

Was it a "this is the way that bc worked in the 70s because it was easier to write a parser for it?" or was there some more underlying reason for the "this problem gets really icky if unary negation has lower precedence than the binary operators and makes for other expressions that become less reasonable?"

It's like the Logical XOR issue ( https://youtu.be/4PaWFYm0kEw?t=2236&si=Wi0gwV-XctLGN98I ) ... and I'm of the opinion that there's a real reason why this design choice was made.

(Aside: Some other historical "why things work that way" touching on dc's place in history: Ken Thompson interviewed by Brian Kernighan at VCF East 2019 https://youtu.be/EY6q5dv_B-o?si=YKr4j_FAEp-OihiX&t=1784 - it goes on to pipes and dc makes an appearance there again)


Unfortunately, I can't really say much about historical design.


Fortunately these rules are natural and easy to remember, especially the details of how different languages choose different orders, relative to the confusing and abhorrent prefix notation (- (^ 3 2)) or (^ (- 3) 2).


As a lover of prefix and postfix notation, there is an unambiguous parsing of each of those that does not deepened on any order of operations. Neither lisp nor forth have the question at all - you can only write it exactly as you mean it.

    (- (expt 3 2))
is always -9 without needing to ask which has higher precedence.

    (expt -3 2)
is likewise always 9. There is no question if - is a binary or unary operator in prefix notation and what its order of operation should be.

Likewise, in dc

    3 _ 2 ^ p
    _3 2 ^ p
and

    3 2 ^ _ p
where '_' is the negation operator (it can be used for writing -3 directly as _3, but _ 3 is a parse error) return their results without any question of order of operations.

When you start touching infix, you get into https://en.wikipedia.org/wiki/Shunting_yard_algorithm which was not a fun part of my compiler class.

(And yes, I do recognize your credentials ... I still think that lisp and forth (above examples for dc) are better notational systems for working with computers even if it takes a bit of head wrapping for humans).


Notation is a tool of thought and of communication. The clearest example of infix botching both is probably perl style regex.

Postfix is interesting in forth. It makes the stack manipulations very easy to reason about, and the stack is very important there so this looks like a win. The cost is in coherently expressing complex functions, hence the advice to keep words simple. The forth programmers are doing register allocation interwoven with the domain logic.

Lisp makes semantics very easy to write down and obfuscates the memory management implied. No thought goes on register allocation but neither can you easily talk about it.

Discarding the lever of syntactic representation is helpful for communication and obstructive to cognition. See also macros.


Maybe something's wrong with my terminal. In dc:

    3 _ 2 ^ p   gives 0

    _3 2 ^ p    gives 9

    3 2 ^ _ p   gives 0

    5 _ p       gives 0

    _5 p        gives -5
You didn't intend that I should get those zeros, right?


     ~ % dc -v
     dc 6.5.0
     Copyright (c) 2018-2023 Gavin D. Howard and contributors
     Report bugs at: https://git.gavinhoward.com/gavin/bc

     This is free software with ABSOLUTELY NO WARRANTY.
     ~ % dc   
     3 _ 2 ^ p
     9
     _3 2 ^ p
     9
     3 2 ^ _ p
     -9
     5 _ p
     -5
     _5 p
     -5
     (control-D)
The version that I have appears to have _ parsed as an operator in addition to the negation of a numeric constant.


I am the author of that dc.

You are correct about its behavior.

See https://git.gavinhoward.com/gavin/bc/src/branch/master/manua... (scroll down to the underscore command).


I'm using the version from Debian testing:

    dc -V
    dc (GNU bc 1.07.1) 1.4.1
In fact, in my version "-v" as opposed to "-V" isn't recognized as a valid option.

    3 _ 2 ^ p
    0


I am Gavin Howard, the author of the other dc.

My dc does have a few differences from the GNU dc. I added the extension of using _ as a negative sign.

That is why you are both seeing behavior differences.


Thanks for looking all this up, particularly the stuff about spreadsheets. I wonder what real early spreadsheets like Lotus 1-2-3 or even Visicalc would do with "-3^2". I have to feel one of the early spreadsheet programmers just made a mistake, because I can't think of a practical reason for going against the mathematical convention if they were already aware of it. Or maybe it comes from bc? ... does bc predate modern spreadsheets?

(Well, I just tried "=-3^2" in an org-mode table and it gives "-9".)


You've got to go even earlier... which is where the bc link becomes interesting. It's from 1975.

Lotus 1 2 3 dates from 1983... I can't find a copy of it that is runnable.

VisiCalc would be a good one to look at at 1979. It also presents 9 https://archive.org/details/VisiCalc_1979_SoftwareArts

You've also got sc https://en.wikipedia.org/wiki/Sc_(spreadsheet_calculator) from 1981.

    docker run -it ubuntu:latest
    # apt-get update
    # apt-get install sc
    # sc
    = -3^2
And you'll see 9.00 (screen shots of those two https://imgur.com/a/L0ZvJlP and the one from VisiCalc )

This is the way its worked for a long time.

---

(edit / further thoughts)

I believe that the underlying issue is that unary - (negation) and binary - (subtraction) use the same operator and you need the unary one to have a very high precedence to avoid other problems from happening.

Consider the expression: 2^-2

Is that 0.25 or a parse error?


Unary and binary - can be given different precedence, because there is never ambiguity as to whether you're in front of a unary minus or a binary minus. A binary operator is never encountered at the beginning, or after a parenthesis, or after another binary operator, therefore those are the cases where you'd have a unary - or +.

Rather, the problem is whether -2 is parsed as a numeric literal, or a unary minus followed by a numeric literal (which would only include positive numbers).


Why would the expression 2^-2 pose a problem? There is no ambiguity there that requires operator precedence to resolve.


Correct, but irrelevant to the question. The usual rules of math require it to be parsed like -(3²), so there are only positive numbers being multiplied.


How we right negative literals in expressions is the issue. Nobody would seriously think -x^2 = -4 had no non-imaginary solutions. But if we swap out x for a literal number people start interpreting it ambiguously as maybe a negative number exponentiated, but fundamentally it’s the same syntax as before.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: