Proposal: Exponentiation operator #8929
Replies: 133 comments 20 replies
-
Why not |
Beta Was this translation helpful? Give feedback.
-
Is this really so much better than using static System.Math;
var result = Pow(a, b); |
Beta Was this translation helpful? Give feedback.
-
Yes, VB has it so it makes translation easier, also makes mathematical expression easier to read but the second point could be debated. Sent from my iPhone
|
Beta Was this translation helpful? Give feedback.
-
👍 |
Beta Was this translation helpful? Give feedback.
-
Yes, a However, would it be possible to add this operator and not interfere with the dereference operator ( F# also uses |
Beta Was this translation helpful? Give feedback.
-
VB's The second argument about math operations being easier to read is the more relevant argument in my opinion. |
Beta Was this translation helpful? Give feedback.
-
VB's |
Beta Was this translation helpful? Give feedback.
-
@LMLB 's argument is the most convincing to me- C# 7.0 is adding digit separators and binary literals for the "defining a constant" use case, and this seems at least as useful as either of those features. |
Beta Was this translation helpful? Give feedback.
-
I think more pertinent to this specific use case is that the operator can be overloaded whereas |
Beta Was this translation helpful? Give feedback.
-
It is. Exponentiation is no different from addition or multiplication: it is a common mathematical operation for which there is a universal notation (including precedence rules) that is approximated in programming languages. C doesn't have an exponentiation operator, while it does have operators for closer to the metal operations like bit-wise xor ( Furthermore, while operators are in scope and will be used when the defining type is in scope, this is not true for the static import in your example. It doesn't work within the scope of a type that itself defines a
Not exactly. There are some small differences. For example, the LINQ expression tree for the VB operator uses a binary expression of type @gregsdennis It is possible to overload the VB operator from C# manually, i.e. by defining a static It would be better if this was all consistent: have all common mathematical operations available as operators that can be overloaded in the same way and that makes them accessible to all .NET languages. |
Beta Was this translation helpful? Give feedback.
-
Citation? :) |
Beta Was this translation helpful? Give feedback.
-
If you're in the type itself, you don't need the static import. You can just directly call "Pow(x, y)" |
Beta Was this translation helpful? Give feedback.
-
But you can't access another type's In the code below, class
This is like someone from Texas asking a Canadian for a citation that snow is a common weather phenomenon. :) Just because something isn't common in your experience doesn't mean it's not common for other people. But since you asked: the code sample in the documentation for the |
Beta Was this translation helpful? Give feedback.
-
Is exponentiation more common or important than square root? Where do you draw the line of which operations are important enough to deserve an operator? The only benefit, IMHO, is that you can use mathematical operators statically. However, I think the constexpr feature (dotnet/roslyn#15079) is a lot more general so I'd be in favor of that to fulfill that use case rather than adding a new operator. |
Beta Was this translation helpful? Give feedback.
-
Related #14665 but like @MgSam said please check #15079, if you like the idea join the discussion. :) |
Beta Was this translation helpful? Give feedback.
-
You could add your own extension method to make this infix. then you'd have You full example would be: A = (2.457 * LOG(1.0 / ((7.0 * ReInv).Pow(0.9) + 0.27 * e_over_d))).Pow(16)
B = (37530.0 * ReInv).Pow(16)
FanningFactor = 2.0 * ((8.0 * ReInv).Pow(12.0) + 1.0 / (A + B).Pow(1.5)).Pow(Exponent) Which also reads fine to me. |
Beta Was this translation helpful? Give feedback.
-
There is also notably not a whole lot of difference between the two. You're basically trading The entire expression as written (for either Fortran or C#) is pretty hard to read. If I saw that code in a PR to dotnet/runtime, I'd like flag it and ask for it to be explicitly broken apart so that it's easier to read and debug. I would likely also require an explanatory comment to exist which gives the mathematical algorithm it corresponds to and an explanation of how its accounting for binary floating-point inaccuracies. |
Beta Was this translation helpful? Give feedback.
-
That's a good idea - I think I'll write that extension method. It more or less solves the readability problem for me. |
Beta Was this translation helpful? Give feedback.
-
I'd have to disagree with this. Let's take a simpler example.
This makes makes my point for me - you're trading a context-giving operator,
Putting something up front doesn't make it clearer, especially when sub-expressions are involved. We read infix operators as infix operators. Clarity is lost, not gained, by rearranging standard math operators to fit syntax. Note, things like
Math-heavy code generally seems difficult at first, but breaking down equations doesn't always make them easier to read. You're inventing new variables for sub-expressions that don't necessarily mean anything by themselves. What about the distance formula (
Sure, but has nothing to do with whether |
Beta Was this translation helpful? Give feedback.
-
I honestly disagree. This reads great to me. Maybe it's not 'better' per se. But it's easy and extremely clear. So there's little motivation to come up with an alternate given that.
|
Beta Was this translation helpful? Give feedback.
-
You have lost no context, the method name makes it very clear what you're doing. In the case of You then have to rationalize that Beyond that, you also have to rationalize all the problems and edge cases that exist with this operator. The fact that it's not efficient for integers, that it can trivially overflow for integers (as per a different comment above, you get around 45k valid combinations and of those, ~42.1k of them are
Yes, it can make it harder to rationalize about, but so can very complex arbitrary expressions. That's why it's typical to break your code apart for readability/maintainability.
This is a terrible way to implement distance. Not only is it incredibly inefficient (calling a function, Even if you were defining it naively and not accounting for precision, you would want to explicitly store double dX = x1 - x2;
double dy = y1 - y2;
return double.Sqrt((dX * dX) + (dy * dy))` Even more ideally, you've appropriately exposed a public static Vector2 Distance(Vector2 x, Vector2 y)
{
float sum = Vector2.Sum(x - y);
return float.Sqrt(sum);
}
Documentation, which exists for the consumer of the API is not the same as code comments, which exists for the implementor/maintainer of an API. One is about the public surface area and the other is about the inner implementation details. |
Beta Was this translation helpful? Give feedback.
-
Note, it's not somewhat ambiguous, It's very ambiguous. For example, this is legal today: using System;
public class C {
public unsafe void M(int b, int* a) {
var x = b ** a;
}
} :D |
Beta Was this translation helpful? Give feedback.
-
What might be more interesting to discuss would be if the language could allow for certain static methods exposed on the type to be accessed like instance methods. That is to say, today you have There is, however, no way to allow for a Perhaps if the language opted to relax its lookup rules to be |
Beta Was this translation helpful? Give feedback.
-
@CyrusNajmabadi My comment was quoting from and responding to @tannergooding's comment - I actually replied here and also acknowledge in replying that the infix nature of an extension method as you suggested is much more readable. |
Beta Was this translation helpful? Give feedback.
-
I work with a lot of It'd be nice if C# comments (including XML doc) had more convenient built-in support for Markdown-like and/or TeX-like syntaxes. Comments are at least as important as "real code", and it feels like they're just ignored for planning and feature development. |
Beta Was this translation helpful? Give feedback.
-
@tannergooding I think your reply really misses the mark on the whole point of this discussion: whether an exponentiation operator would be a useful addition to the C# language. Arguing about whether a specific example is optimal in terms of speed or accuracy doesn't have anything to do with whether an operator adds value. The purpose of my examples was to show the benefit of an operator. Yes, code needs documentation (obviously). Yes, penny pinching CPU cycles could lead someone to trade the brevity of x**3 for x * x * x. Yes, floating point precision should be weighed and accounted for. But what does that have to do with adding an operator? To that end, I won't be addressing the criticism of my specific implementation of the distance formula nor the proposed API changes.
Here's my original example
This is the context to which I was referring: the mental ability to parse what's going on. Is all the information technically there for you? Sure. Should the code be broken down? Probably! But it's (subjectively) harder to read, and thus to me serves as a good example. I will reiterate from other replies: I think the extension method
I'm not advocating for |
Beta Was this translation helpful? Give feedback.
-
I don't really agree with this. The idea here is that we're not inventing anything. We're using what the language already has and supports. :) And our preference is that if the lang already has a good solution for a problem, we'd prefer to keep using that versus introducing a new solution (cuz now you have multiple :)). So we need strong reasons to add features. And that includes strong arguments for why the existing options available at the language level are not sufficient, and thus why something new does need to be "invented" :) |
Beta Was this translation helpful? Give feedback.
-
A lot. If the operator is trivially rejected because it is the wrong thing nine times out of ten or has other super common problems, then that is a reason to not expose the operator. If there is then a simple alternative, like defining an infix API, which solves the problem and introduces less complexity to the language, that then becomes a better direction. Especially if that also gives users more flexibility for the entire set of math APIs rather than being scoped to simply
You can trivially create complex expressions even with purely using operators that are hard to read/understand and even where users will commonly get the logic wrong because they misunderstand things like order of operations. Consider, for example, the following which is only using multiplication and addition. It is part of the real algorithm used to implement (((r04 * C20) + ((((r * C19) + C18) * r02) + ((r * C17) + C16))) * r16) + (((((((r * C15) + C14) * r02) + ((r * C13) + C12)) * r04) + ((((r * C11) + C10) * r02) + ((r * C09) + C08))) * r08) + (((((r * C07) + C06) * r02) + ((r * C05) + C04)) * r04) + ((((r * C03) + C02) * r02) + r) Which is much more readable, but still very verbose and hard to parse/understand, if you break it apart like this (and it could be more readable/understandable with locals and/or the surrounding comments in the actual code): (((r04 * C20)
+ ((((r * C19) + C18) * r02)
+ ((r * C17) + C16))) * r16)
+ (((((((r * C15) + C14) * r02)
+ ((r * C13) + C12)) * r04)
+ ((((r * C11) + C10) * r02)
+ ((r * C09) + C08))) * r08)
+ (((((r * C07) + C06) * r02)
+ ((r * C05) + C04)) * r04)
+ ((((r * C03) + C02) * r02) + r) Code has to be broken apart for readability/legibility. This is even true in real math and is the whole reason Algebra has named variables. |
Beta Was this translation helpful? Give feedback.
-
The probably one (now two) people who wrote a line that looked like that can afford a compilation error I think :) I have felt the few times I write exponentiation it does look ugly, and tears up expressions a bit, especially when I'm translating from a math formula. Not a hill I would die on, but I wouldn't mind an exponentiation operator either. |
Beta Was this translation helpful? Give feedback.
-
This avoids pointer problems and is also readable |
Beta Was this translation helpful? Give feedback.
-
Consider adding an exponentiation operator that is higher in precedence than the multiplicative operators but lower in precedence than the unary operators.
In the Symbolism computer algebra library,
+
,*
,/
, and-
are overloaded to createSum
,Product
,Quotient
, andDifference
objects respectively.^
is also overloaded to createPower
objects. However^
, being the logical XOR operator, is lower in precedence than the multiplicative operators. Thus parenthesis must be used in expressions likea + b * (c ^ e)
.MSDN - C# Operators
Exponentiation operator in some other languages:
**
^
**
**
**
^
,^^
,**
**
**
**
^
**
*
Beta Was this translation helpful? Give feedback.
All reactions