-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Exponentiation by a negative power throws a DomainError #3024
Comments
Did you intend to close this? |
Either way, I don't think we're going to change this. |
Yes, I realized that it was a silly misunderstanding. Negative float exponents work fine: 2 ^ -2.0 |
I don't understand why this error on Julia. On Julia:
On R:
On Python:
People can't do this:
Maybe a better error message? |
Type-stability, which other dynamic language completely ignore. There's a long discussion in an old issue about this. This was the best compromise we could come up with, although it is admittedly annoying. |
So the integers are not closed w.r.t. division and inversion (raising to negative integer powers). Julia addresses this by:
P.S. In contrast, rationals CAN of course be raised to negative integer powers:
But be careful: 2//3^(-1) does throw DomainError, because ^ binds tighter than //. If 3^(-1) would instead automatically produce a float, we would get the same behaviour as for 2//3^(-1.0), which---quite reasonably---throws: ERROR: no method //(Int32,Float64). |
Hmm, would it perhaps be possible to define a new operator: "^-", defined so that:
|
Oh, that's dastardly. I think I might like it. Because most of the time this is a purely syntactic negation that is actually quite safe. The case of |
This would make the relationship between
|
Perhaps you guys can add some more message for this error. It is really surprising to see it the first time. |
We should improve the error message as part of #4744. |
Negative powers are just too common. Some time ago I used a lot (just a user) |
@miguelbarao Replacing |
@miguelbarao, the problem is that currently "fast = type stable." You can have a slow |
I think the problem here is really that |
What is this, JavaScript? :-P |
I'm still not entirely convinced that having a |
I think |
That it certainly does. |
Or even worse; Why did my huge formatting clanup create bugs that were only discovered in production, when I changed |
If the error message was explicit enough, I guess raising an error wouldn't be a problem. |
Isn't the obvious analogue to |
The trouble with that is that one wants |
As the proposer of the new operator ^- , I admit that it would lead to more confusion and more problems than it would solve, so let's forget about that one. However, I do think the error-message for negative exponents of integer arguments could be more helpful. Let me propose that we do not look at integer exponentiation in islolation. There are other functions with similar behaviour, for example log() and sqrt(), which in other languages would automatically map negative real arguments to complex outputs, but in Julia give DomainError. I get: julia> log(-1) julia> sqrt(-1) julia> 2^(-1) It would be nice if this one could give a similar message to the ones given by log() and sqrt(). |
+1 for a helpful message. I'll fix that. |
I believe it all boils down to the intended audience of the Julia language. I think most people coming from physical sciences and engineering disciplines (like me) will expect I would expect the behavior to be:
Making the parallel with python, they replaced the integer division Not sure about this, but another route could be to ensure type stability by distinguishing between natural and integer numbers (unsigned/signed)? A natural number would be promoted to integer just like an integer can be promoted to a float.
There are other places where the current way of doing exponentials can lead to problems:
When the exponent is the result of a computation with error accumulation, this does not work. Example:
I understand that it is not easy to draw a line. Sometimes we want a domain error, other times we want a complex number, but I feel there is much inconsistency here. I'm currently considering doing things like @ivarne the error message in |
FWIW, I don't really think there's any inconsistency here. I think there's a tension caused by Julia using integers, when most of the other languages (matlab/octave/R) use floating numbers for everything and invest a lot of energy into pretending that floating point numbers are integers. There's clearly a reason that scientific languages have done that, but I think Julia is intentionally encouraging users to work with integers more often than traditional scientific languages have. |
@miguelbarao: The methods of There are ways to make a |
Although "try it and see" might be relevant advice here. |
@toivoh Thank you. Redefining |
I do think it's worth considering whether |
@miguelbarao: Yes, the downside to that is that you might break other people's code that relies on the current behavior for performance or correctness. |
@miguelbarao The "consistent" behavior you want is easily attainable: use floating point numbers for all operations. The result type of an operation is always something you have to learn about for each operation individually, so it's not at all surprising that division and exponentiation should produce different results. In modular arithmetic, for example, integer exponentiation of the sort Julia provides is trivially definable for moduluses, whereas the behavior of division is something that depends strongly on the modulus and requires some subtlety to define meaningfully. This is also true of matrices: exponentiation to a positive integer is trivial to define, but division is much harder. So I don't find contrasting @timholy's point is a good one, but it involves a change that's potentially undesirable: it makes exponentiation and multiplication more dissimilar because you can't replace |
Lets put it in another way (user point of view, like me):
Now with floats:
So floats are actually faster. It could be argued that integer powers are usually small numbers. Let's see: raising only to very low powers, say 2 to 5:
So it's nearly double the speed for small exponents. We could call it a draw performance-wise. Am I doing something wrong?
If all this doesn't make a point (and there are still other issues in the exponentiation), I guess Julia is just not for my mindset and should look elsewhere. Really a pity because Julia has a lot of potential and I really admire your work. |
@miguelbarao: Why not just use floating point numbers all the time? That's clearly what you want and is already available in Julia without any changes being made. Instead of writing |
That's actually a very interesting point. What if |
@johnmyleswhite Because I'm promoting the use of Julia with my students and whenever I have a problem like "Consider a bag containing N balls, what is the probability of getting the same ball M times", I get these answers: |
I'm always perplexed that a single nit with one of the many tough decisions and tradeoffs that are necessary to create a good general-purpose language can put some people off of something which they otherwise thought was great. Usually it's overflow of We should definitely fix the error message and then be done with this. Even students (who are notoriously unable to learn new things) should be able to handle the current behavior if they're given a nice clear error message when it happens. |
@miguelbarao, it might be worth putting together a "Finesse.jl" package for your students that throws specific warnings for errors that students frequently make, and either auto-converts or throws an error (depending on the level of the class, your goals, etc). The documentation is pretty good at directions for setting up packages, and the users mailing list can help as well. |
There's more breath being wasted on the conversation than in just fixing the problem. See #8784. |
👏 @timholy |
@miguelbarao, my adding the error doesn't necessarily mean that no further changes are possible. But you're going to have to do the work (this is open source, after all) and address the concerns. If you go with a floating-point base, you'll need to address the one raised by @johnmyleswhite, how one explains for |
Raise informative error for exponentiation to negative power (see #3024)
@timholy 'x = 10^23' overflows as Int64 and |
OK, try this:
|
In other words, it's a problem with values, not types. |
FWIW, when introducing integers Lua decided that |
Note that |
@stevengj After reading this long discussion, I found that ^ is now type-unstable (now that #24240 is merged), just as @StefanKarpinski said in this post in #20240. So, if I understand it correctly, we gave up the principle of type-stability, only for the sake of coding convenience? (in this case, 2^-2.0 is necessary for efficient compilation, 2^-2 will work but leads to inefficiency) |
Better to ask this kind of question on discourse than here. In short (please continue on discourse), referential transparency that was sacrificed, not type stability: |
This fix works for me:
The text was updated successfully, but these errors were encountered: