Why Euler's number e = 2.71828... is not a built-in constant in MATLAB?
586 次查看(过去 30 天)
显示 更早的评论
Kareem Elgindy
2020-6-17
I understand that we can produce that number in MATLAB by evaluating exp(1), or possibly using exp(sym(1)) for the exact representation. But e is a very common constant in mathematics and it is as important as pi to some scholars, so after all these many versions of MATLAB, why haven't they recognize this valuable constant yet and show some appreciation by defining it as an individual constant rather than having to use the exp function for that?
Below is a conversation between me and MATLAB illustrating why MATLAB developers have ZERO common sense... Enjoy the conversation dear fellows and no regret for MATLAB staff...
Me: Hello MATLAB, how is things?
MATLAB: All good! How can I serve you today sir?
Me: Yes, please. Could you give me the value of Euler's number? You know... it's a very popular and fundamental constant in mathematics.
MATLAB: Sure, but wait until I call the exponential function and ask it to evaluate it for me...
Me: Why would you call the exponential function bro??? Isn't Euler's number always constant and its value is well known for thousands of digits?
MATLAB: You will never know sir... Maybe its value will change in the future, so we continuously check its value with the exponential function every time I'm turned on...
Me: You do WHAT!!!
MATLAB: Well... This is a normal procedure sir and I have to do this every time you turn me on...
Me: Stop right there and don't tell me more please...
MATLAB: No, wait sir... I agree with you that this is perhaps one of the most cloddish things that was ever made in the history of programming, but what can I do sir? The guys who developed me actually believe that this is ingenius.
Me: Ooooh oooh ooooh.... reeeeeally!!! Now ain't that something...
MATLAB: They say sir that this is for your security plus there are no applications for that number sir, so why should they care? Even Euler himself, if resurrected again, would fail to find a single application for that number sir. Probably Jacob Bernoulli, the first to discover this number in 1683, would fail also sir, so why should we bother sir? Though it's a mathematical constant and deeply appreciated by the mathematicians around the world for centuries, we don't respect that number sir and find it useless.
Me: Who decides on the importance of Euler's number as a mathematical quantity? Mathematicians or the guys who develop you?
MATLAB: The guys who develop me sir; right?!?!?!?!?
Me: Bro I was obsessed with you in the past and I was truly a big fan of you for more than a decade. But, with the mentality I saw here from the guys who develop you, I believe you will beset with fundamental issues for a long time to come bro... No wonder why Python have beaten you in many directions and became the most popular programming language in the world. Time to move to Python you closed minded and thanks for helping me in my research works in the past decade!!! Good bye for good.
MATLAB: Wait sir... Don't leave please... As a way to compensate for the absence of Euler's number, we offer the 2 symbols i and j sir to represent the complex unity, so the extra symbol is a good compensation for Euler's number...
Me: What did you just say?
MATLAB: Say what?
Me: You provide 2 symbols to represent the same mathematical complex unity quantity, but you have none for Euler's number???
MATLAB: Yeeeeeeeap... you got it.
Me: You can't be serious!
MATLAB: I swear sir by the name of the machine I'm installed in that this is true; I'm not making that up.
Me: But why 2 symbols for the same constant; pick up one for God sake!
MATLAB: Well... There is a wisdom sir for picking 2 symbols for the same constant not just 1.
Me: What is it?
MATLAB: Have you seen the movie "The Man in the Iron Mask" written by Alexandre Dumas and Randall Wallace or read the novel "The Three Musketeers," by the nineteenth century French author Alexandre Dumas sir?
Me: I only saw the movie. But why???
MATLAB: Then you must have heard the motto the movie heros lived by in their glorious youth, "One for all, all for one".
Me: Yes, I did...
MATLAB: We sir were very impressed by this motto, so we came up with a new one.
Me: Impress me!
MATLAB: "i for j, j for i".
Me: You're killing me...
MATLAB: Wait sir, there is more...
Me: More what?????
MATLAB: Many experts around the world project that the number of letters to represent the complex unity in MATLAB may reach 52 letters sir by the end of 2050, so that you can use any English letter (capital or small) to represent the complex unity. How about this sir? Ain't this ingenious also? Sir ?!!?!?!?!?
Me: And this is when common sense was blown up by a nuclear weapon... This circus is over...
24 个评论
Kareem Elgindy
2020-6-17
Thank you so much... Very reasonable answer indeed... Yet there are many workarounds about this issue. For example, a simple modification like keeping the first few letters of Euler's number would do the trick without confusion. Naming it like eu, or Eu wouldn't make any harm and still serves the purpose adequetly.
Bjorn Gustavsson
2020-6-17
Further, most everywhere it is used it will appear as e-to-the-power of something, i.e. exp(something)
David Goodmanson
2020-6-17
编辑:David Goodmanson
2020-6-17
Hi Kareem,
not quite as good, but you can always make your own and store it somewhere on matlabpath.
function x = ee % or whatever it might be
x = 2.718281828459046;
end
Kareem Elgindy
2020-6-17
编辑:Kareem Elgindy
2020-6-17
Thank you all for your nice contributions. I think David's solution is fantastic. I can now define my own function with whatever name I wish to have and use it to produce Euler's number.
For example, I can keep e as a scientific notation for 10, but leave E for Euler's number. Anyway, MATLAB distinguishes between small and capital case letters, so this would be a temporary solution for me until MATLAB would finally listen to this call and do something more intelligent about it.
Kareem Elgindy
2020-6-18
I think en would be a good name for a user-defined function that gives Euler's number. It's a matter of taste anyway!
Kareem Elgindy
2020-6-18
Thanks KSSV. I initially thought of E like you as a good choice, but I found that it is also a scientific notation that stands for 10-- the same like e. To avoid any confusion about this matter I came to prefer en as it seems that it doesn't conflict with common scientific notations and there is no built-in MATLAB function that holds this name; plus, en are the initials of Euler's number and still close from the usual mathematical notation e. I created and shared a very simple code that gives this number using en yesterday. You can find the file via https://www.mathworks.com/matlabcentral/fileexchange/77046-euler-s-number.
Kareem Elgindy
2020-6-18
Good point Stephen. E could be confusing indeed, unless MATLAB Development Team decided to keep only e as a scientific notation for 10, so that E becomes a free variable that we could possible use for Euler's number. I contacted MATLAB Development Team to consider this urgent matter; hope they will consider it in future releases of MATLAB.
Kareem Elgindy
2023-7-2
编辑:Kareem Elgindy
2023-7-2
It's interesting to note that Python Developers define Euler's number as a built-in constant by invoking the supporting module math. In particular, math.e gives 2.718281828459045 without the silly computation of the exponential function at 1 as in MATLAB.
Thumbs up Python Developers 👍
Rik
2023-7-2
If you still refer to it as 'silly computation', you should re-read the paragraphs below. You may call it roundabout and have a point, but silly it is not.
And nothing is stopping you from doing the same in Matlab.
Kareem Elgindy
2023-7-2
Instead of simply calling a well-known constant like e, you guys have to go the long way of calling the exponential function and then evaluate it at 1!!! How silly this is!!! Compared with you guys, Python Developers are very open minded. Thumbs up again for Python. I'm one of thousands of programmers considering to move and code with Python in the near future. I just finished an online course on Python recently and I found it to be very useful. Hope MATLAB Developers become more open minded people like Python Developers are. Actually, there is nothing stopping you from being so... Good luck!
Steven Lord
2023-7-2
As Rik said, this is easy to do in MATLAB.
classdef math
properties(Constant)
e = exp(1); % Or you could hard-code the value
end
end
Or create a function e.m and put it in a package directory +math in a directory on the MATLAB search path.
Rik
2023-7-3
It is only silly on the surface. You never just need e. You always use it for something. And the moment you need it, you can get extra precision for free because of this. If e was available as a constant, people would do e^x, instead of exp(x). If you can't acknowledge the benefits of this structure, perhaps we might not be the closed minded people here...
James Tursa
2023-7-3
编辑:James Tursa
2023-7-3
@Kareem Elgindy I for one am still puzzled by your attitude. As has been pointed out several times to you, MATLAB can behave exactly as Python does if you want it to. If you want to make e known to all your code as Euler's number just put a function on your path called e.m that returns the value. Or if you want it to be returned as a "value from a module" you can define a class called math with a public property called e so you can use math.e in your code making it look very much like Python. This can even be self documenting. Just put this classdef on your path and you don't even have to explicitly import it like you would in Python. Since you can easily get the same behavior as Python (even though this method has been shown to you to be inferior), what is the problem?
Rik
2023-7-4
I also don't understand your theatrics. In Python you need to load the math package, in Matlab you will have to use e=exp(1);.
What is your problem? If you want e as a number, you can easily do it. You have even posted a function on the file exchange. And as shown below, you get precision for free by using the exp function. So there is a reason. That you chose to ignore the reason and make fun of this is your problem. Nobody (or hardly anyone) is interested in the value of e. Everybody wants to do something with it. Since the most common usage is exponentiation, it makes sense to have it this way.
It seems you are refusing to acknowledge that there actually is an advantage, because otherwise people will use e^ instead of exp, hurting both performance and precision. So who is being closed minded? You keep accusing us of being closed minded, but you refuse to acknowledge this point, instead choosing to make fun of the situation. If your next post is that childish again, I will be out.
Steven Lord
2023-7-5
Just a reminder to everyone in this discussion, the MATLAB Answers Help states "Be honest and considerate with all responses to all contributors." [It actually states that twice, once in "Tips for Creating Helpful Answers" and once in "Tips for Making Comments Helpful".]
Rik
2023-7-6
I see such a stark difference between the original comments of OP and the current style of writing comments, that I'm wondering if it is even the same person.
It is trivially easy to ignore any explanation and write a play making fun of the situation, but why bother? I'm not convinced by that mock dialogue, and I doubt anyone else will be. Meanwhile there are actual reasons for why it works this way, and those reasons are not acknowledged. It would even be perfectly reasonable to acknowledge it and express the opinion that it isn't a good enough reason. But neither of these options were chosen.
@Kareem Elgindy you can keep editing and expanding your childish post, but I hope there are more productive ways to spend your time. Please either write a normal response, or stop posting in this thread.
Matt J
2023-7-6
编辑:Matt J
2023-7-6
But e is a very common constant in mathematics and it is as important as pi... As a way to compensate for the absence of Euler's number, we offer the 2 symbols i and j
Note, pi, i, and j are also not builtin Matlab constants. They are function-generated as well:
>> pi(1)
Error using pi
Too many input arguments.
>> i(1)
Error using i
Too many input arguments.
>> j(1)
Error using j
Too many input arguments.
Steven Lord
2023-7-7
Me: You provide 2 symbols to represent the same mathematical complex unity quantity
That's correct. MATLAB allows users to use either i or j in constructing complex numbers. You see Cleve Moler, the chief scientist and co-founder of MathWorks and the original author of MATLAB is a mathematician and the standard way to write sqrt(-1) in mathematics is i. But Jack Little, president and co-founder of MathWorks, has a background in electrical engineering. [See the section titled "Jack Little" in that post on Cleve's blog.] MathWorks products are quite heavily used in various engineering fields, and in engineering fields where i means something else the square root of -1 is commonly denoted as j.
From Wikipedia: "In contexts in which use of the letter i is ambiguous or problematic, the letter j is sometimes used instead. For example, in electrical engineering and control systems engineering, the imaginary unit is normally denoted by j instead of i, because i is commonly used to denote electric current."
So this isn't a MathWorks convention, it's a math and engineering convention.
回答(2 个)
John D'Errico
2020-6-18
编辑:John D'Errico
2020-6-18
Let me add this as an answer, because there are very good reasons to leave e as not a named constant, instead of naming it. Yes, they could have given you e, as well as pi and i. To be honest, there is just as good of an argument to have created many such named constants. For example, phi, the golden ratio. phi appears in zillions of places in mathematics. Luckily, phi is easy to compute, as
phi = (1 + sqrt(5))/2
phi =
1.61803398874989
in case you ever need it. Or you could compute it in this form equally useful form:
phi = (sqrt(5) - 1)/2
phi =
0.618033988749895
which happens to be just the inverse of the first.
But then there is the Euler-Mascheroni constant, often called the Euler gamma, or just gamma by some. And we already have a hugely valuable function named gamma, which computes the gamma function. I use gamma a LOT as a function. But some people would want to see the Euler gamma as a constant too.
You can actually find this in the symbolic toolbox as eulergamma.
vpa(eulergamma)
ans =
0.5772156649015328606065120900824
Note that it exists as a function with a long name, but it is there if you need it. And some people would have great arguments to include Avogadro's number, the Planck constant, or the speed of light. So there are some named constants. But really only the two of them. If it bothers you, you could theoretically write a function for e, but in fact, I strongly recommend that you do not do so in the case of e!
It would not have cost a lot, or so it would seem. It would have created some possible places for confusion as the comments suggest, because e is used by itself as an indicator of scientific notation.
If for some reason, you wanted the number, you can always compute it directly as exp(1). So this is even easier than computing the golden ratio constant. But let me ask you this: Why do you think you want it? Why do you think you want the number e in MATLAB?
Really, there is only one reason why you might want to have e laying around. That is to use it in the form e^x. There is a fundamental problem in that idea though, because it is both more efficient and more accurate to use the exp function directly. And exp(x) is used a LOT in mathematics. If the creators of MATLAB wanted to encourage people to compute e^x, they would have provided you with the constant e. But they really don't want to do that.
So you have the function exp. In fact, this is a commonly provided function in almost every computer language you will ever learn. Everything from spreadsheets to fortran to languages like MATLAB and Python. They will have a function probably called exp. It does exactly what you expect. It computes exp(x), and is highly optimized to compute exactly that function to within machine precision.
If you were to start writing it in the form of e^x, then this would put more load on less efficient libraries, that are set up to raise some arbitrary number to a power. In fact, we can even test this out:
E = exp(1)
E =
2.71828182845905
>> exp(2.5)
ans =
12.1824939607035
>> exp(2.5) - E^2.5
ans =
-3.5527136788005e-15
Interesting, no? It looks like exp(2.5) and E^2.5 produce slightly different results. Which is closer to the true value? Remember that E is a number pretty much as close as we can produce in MATLAB, to double precision accuracy. It won't help if you provided 20 significant digits for e, as MATLAB can store only 52 binary bits in the end anyway.
% What MATLAB produces using exp:
sprintf('%0.55f',exp(2.5))
ans =
'12.1824939607034732347301542176865041255950927734375000000'
% If you use E^2.5,
sprintf('%0.55f',E^2.5)
ans =
'12.1824939607034767874438330181874334812164306640625000000'
As you can see, they differ down in the digits where one goes ...034732, and the alternative goes ...034767. But which is closer to the truth? We can test that out using VPA and the symbolic toolbox.
vpa(exp(sym(2.5)))
ans =
12.182493960703473438070175951168
Here we see the correct value of exp(2.5) goes ...034734.
Essentially, we got an extra decimal digit of accuracy, by using the function exp. And it would not have helped if we defined E differently. We still get the wrong answer. Here, for example, I might use the symbolic toolbox to create E. In the end, it will be a double precision number, stored internally using an IEEE arithmetic floating point format.
E = double(exp(sym(1)))
E =
2.71828182845905
>> exp(2.5) - E^2.5
ans =
1.77635683940025e-15
>> sprintf('%0.55f',E^2.5)
ans =
'12.1824939607034714583733148174360394477844238281250000000'
Again, we get a result that is not as accurate as just using exp(2.5).
Thus in terms of accuracy, you want to use the function exp. But there are always two things we care about in computing, accuracy and speed. So how about speed? Here, remember that E is the constant we have created. It is a double precision number.
X = rand(1000);
>> timeit(@() exp(X))
ans =
0.0015833418125
>> timeit(@() E.^X)
ans =
0.0068411758125
Interesting, no? It is actually more than 4 times as fast to compute exp(X) as it was to compute E.^X. What are the odds someone who was doing some truly heavy duty computing would be upset if they saw such a differential in time? Honestly, they would have a fit.
Finally, how about consistency? Suppose The MathWorks decided to do as you wish, and they provided a named constant for e? I don't totally care what short name they chose. Think about what will happen. Now, every time someone tries to compute exp(x) versus e.^x, they might get subtly different results. Different down in the least significant bits, but DIFFERENT! Can you imagine the number of headaches they would have, trying to deal with this? The number of bug reports they would get?
So let me ask you to NOT define your own constant for E. You could do so, as some have suggested. But you will be happier in the end if you don't. You think you want it, but sometimes, what you think you want is an illusion. Just use the function exp, as people all around the world have happily done for many years. There are even several good reasons to do so.
28 个评论
Kareem Elgindy
2020-6-18
编辑:Kareem Elgindy
2020-6-18
Dear John,
Your detailed answer, the time you took to write it, and the effort you made to explain and code examples to support your viewpoint is very much appreciated. However, I have to disagree with you in probably all the points you mentioned. Here is why:
1. Your first argument is based on the fact that all the constants you mentioned like the golden ratio, Euler-Mascheroni, Avogadro's number, the Planck constant, and the speed of light are easy to compute, so no urgent need to define them as I understood from your answer. As you wrote, the golden ratio,
phi = (1 + sqrt(5))/2,
so no need to define it, right? If we follow your argument and apply it on all constants, you will soon realize that your own argument actually contradicts the necessity to define pi as a built-in constant. Notice that all trigonometric functions in MATLAB are well defined, so one can calculate pi as 4*atan(1). Let us check together:
>> format long; format compact
>> pi, 4*atan(1)
ans =
3.141592653589793
ans =
3.141592653589793
>> pi == 4*atan(1)
ans =
logical
1
>> vpa(pi,50), vpa(4*atan(1),50)
ans =
3.1415926535897932384626433832795028841971693993751
ans =
3.1415926535897932384626433832795028841971693993751
Notice that one could also try to use the same algorithm used by MATLAB to compute pi to any desired degree of accuracy and speed. The point is: either they define important constants all together, or don't, as they could easily be calculated using a huge library of valuable built-in functions already written by expert programmers.
2. You gave an example showing that exp(2.5) and E^2.5 produce slightly different results, which is absolutely true. However, one can easily refute this argument by simply creating a MATLAB function called E, or en, or whatever, that calculates Euler's number using the very same method the usual exp(1) is calculated in MATLAB as a built-in function; thus sharing the same accuracy and speed. The user-defined function called en that I created in File Exchange produces correct value for 16 significant digits; however, this function can be easily updated to use the very same algorithm used by MATLAB to calculate it without any difficulty and with the convenience of now having Euler's number well defined in MATLAB the same as pi. MATLAB Development Team can use the very same algorithm they are currently using to define E, for example. So again, and back to the former point: "either they define all important constants used frequently in common scientific areas and applications, or not". I'm one of those researchers who personally view E as important as pi in applications, and I hope this matter will be considered seriously in future releases of MATLAB.
Once again I thank you John for your great efforts and time spent to add your contribution; I deeply appreciate it.
John D'Errico
2020-6-18
编辑:John D'Errico
2020-6-18
Sorry, but I'll simply need to disagree with you. You are wrong, and in many respects.
The Euler-Masheroni constant is NOT something easy to compute. It is typically defined in terms of a limit of the difference between the harmonic series and the natural logarithm, as as an integral. I suppose you can get it from MATLAB in the form of the digamma (polygamma) function.
-psi(1)
ans =
0.577215664901532
But you would need to know where to look for it.
And while 4*atan(1) happens to give the same value for pi as is stored in pi itself, that is not true of e. In fact, as I carefully show, there is NO value we can store for E ~ exp(1) that is as good as using the function exp to compute a general exponential.
You would also need to know where to look for pi in the form 4*atan(1). Most students don't. But it is not difficult to teach then to use exp. And you will find an exp function in everything from a spreadsheet to basic to Fortran to Python. exp is pretty much a standard function in all tools I have ever used.
As for pi being necessary, I think students the world around would expect to find pi in MATLAB. Homework question number 2 or 3 will probably require pi anyway. And pi has surely been part of MATLAB since version 1 came out about a million years ago. I'd bet a sum of money they had the variable pi in version 0.1 of MATLAB when they put together the beta version. I can ask Cleve if you feel it important though.
Anyway, we can argue in either direction about the need for other defined constants in MATLAB. Honestly, I don't give a damn either way, except that if the MathWorks were to create too may defined constants, then it would possibly invalidate all sorts of code people have written over the years. And that IS important. For example, suppose the Mathworks were to suddenly introduce a variable with the name en? At that point, ALL legacy code that employs a variable named en that is something else will now potentially start to see bugs. People will suddenly need to worry if they have variables named phi, en, etc. As it is, we can see problems when people create variables with the name eps. Other named constants, like realmax or realmin seem not to be much of a problem. I've never really seen people trying to trample upon inf or NaN. But I seriously doubt the MathWorks wants to introduce new named constants.
So the solution the MathWorks uses is to totally minimize the named constants they provide. When they do provide something, they give it a name liike eulergamma, that won't get stepped upon very easily. If you want some named constant, feel free to create it yourself. Be careful to make it as accurate as possible, but that is your problem entirely. If MathWorks were to provide a golden ratio constant, I would argue for a name like goldenRatio, something that will be not a problem. A lot of people use phi as a variable name for other things.
The real problem is as I said: e as a named constant in MATLAB will have only one common purpose - to compute e^x for those who don't wish to learn to type exp(x). You have shown nothing that counters my claim.
We CANNOT create a function in MATLAB that will return a double precision number E, that in turn can then be used to compute E^X as fast and as accurately as exp(X) does the same thing. I showed that. REREAD MY ANSWER.
One thing that MathWorks seriously does NOT wish to do is create a variable E, such that E.^X does not give identically the same result as exp(X), ALWAYS. Were this to happen, can you imagine the huge number of furious bug reports they would get?
I even show that if you store the symbolic value of e as a double precision number, you still get the wrong result. This is not something the MATLAB development team can do. They have no magical powers in this respect, because exp(X) actually gives better, faster, and more accurate results. I can imagine the laughter at Mathworks if asked to include functionality in MATLAB that is less accurate, slower, and inconsistent? The first person who tried to do that would be given some job coaching.
Sorry. Just learn to use exp as a function. Or feel free to create your own named constant and use it as you wish. But don't expect things to be fast. Don't expect it to be as accurate. And, really, why do you want something slower and less accurate anyway?
Bjorn Gustavsson
2020-6-18
To your second point: What's the point of that? If you still want to use your such-wise defined Euler's number to calculate an exponent like e^2.5 you will still be worse off, for the exact reasons John explained above. Try:
>> exp(1)^(2+1/2) - exp(2+1/2)
% I got the same error as John showed above: 3.552713678800501e-15
So again same problems with accuracy and reduction in computing time. If you can at least show a use of e that isn't a calculation of exp(x), then you'd start to make another use-case.
Kareem Elgindy
2020-6-18
I enjoyed this communication very much. All contributions are very much appreciated. But the subject still requires further investigation... Hopefully, more information will shed more light on this subject in the near future. I am very happy that this post attracted such attention from various participants.
Steven Lord
2020-6-18
编辑:Steven Lord
2020-6-18
Commenting on a couple points John D'Errico brought up:
So you have the function exp. In fact, this is a commonly provided function in almost every computer language you will ever learn.
In fact, the IEEE standard for double precision (IEEE 754) lists exp as a recommended operation. [To be fair it also recommends exp2 and exp10. We have exp2 as pow2 with one input but we don't have exp10. We also don't always throw the exceptions the IEEE spec suggests, since we have complex numbers available.]
As for pi being necessary, I think students the world around would expect to find pi in MATLAB. Homework question number 2 or 3 will probably require pi anyway. And pi has surely been part of MATLAB since version 1 came out about a million years ago. I'd bet a sum of money they had the variable pi in version 0.1 of MATLAB when they put together the beta version. I can ask Cleve if you feel it important though.
One difference between pi and e (just IMO) is that pi is often used "in isolation" as just a number. The most common use case for e is as the base for a power operation e^something. If pi were only ever used in the context of sin(pi*something) we'd probably only provide a sinpi function.
And pi wasn't in Cleve's original MATLAB (you can see in the User's Guide that in one of the examples he computes it using atan) but it was in PC-MATLAB 1.0 (or at least 1.3, since Cleve mentioned that was the earliest disc he could find. See the Contents section here.)
For example, suppose the Mathworks were to suddenly introduce a variable with the name en? At that point, ALL legacy code that employs a variable named en that is something else will now potentially start to see bugs.
Actually, it's likely the opposite. Remember that variables are higher precedence than functions. If we introduced a function named en and people had:
en = 42;
in their code, they wouldn't be able to call the en function until or unless that variable no longer existed. See:
sum = 0;
sum = sum + ...
% now try to call the sum function
y = sum(x) % likely error or unexpected result
If we made en a keyword like if, for, and while that could break code. But we don't introduce new keywords that often (arguments is I believe the most recent one) and context does matter (methods is only a keyword inside a classdef file.) As precedent, pi isn't a keyword.
James Tursa
2020-6-18
A quick follow up about pi. It is often used in "isolation" as John and Steven mention, but it is also often used as part of arguments to periodic trig functions. These trig functions apparently have special code to effectively do the mod 2pi argument reduction to high precision (more than double). It might be nice if MATLAB provided this "high precision mod 2pi" capability as a standalone function, so that users could match what the trig functions do in their own code. E.g.,
>> x = 1e17;
>> sin(x)
ans =
-0.464530104835373
>> sin(mod(x,2*pi)) % Naive mod 2pi fails to match MATLAB
ans =
0
>> mod2pi = @(x) atan2(sin(x),cos(x))
mod2pi =
function_handle with value:
@(x)atan2(sin(x),cos(x))
>> sin(mod2pi(x)) % Our own mod 2pi function matches MATLAB
ans =
-0.464530104835373
>> sin(vpa(x)) % vpa matches also
ans =
-0.46453010483537269615452411397506
>> double(ans)
ans =
-0.464530104835373
>> mod(x,2*pi) % range is too great for mod function
ans =
0
>> mod2pi(x) % but not custom function
ans =
-2.658488737094681
So, I can mimic what the trig functions are doing in the background with argument reduction with my own mod2pi function, but it costs me three trig function calls to do it.
John D'Errico
2020-6-18
I can understand wanting things to be different, to meet your expectations of how mathematics is usually written. But MATLAB is not really a WYSIWYG tool. Instead, it is much more of a text based language. It is optimized for efficiency in usage. We want things to run as fast as possible, to be as accurate as possible. Otherwise we would use a different tool.
For example, long ago, I was using MathCAD for a little while. I'm not even sure that tool is still around. But I recall spending time working with the tool, trying to use it for some computations. I even spent time working with the developers, trying to get them to deal with and repair numerical issues. I gave up, because it seemed at least in the early days that they were more worried about how things looked than how they worked. Again, I have no idea if the tool is still around, and I am sure it has improved since then if it still is.
So yes, the interface is important. But typing in exp(x) compared to perhaps E^x, e^x, or en^x is small potatoes. And if the cost in that computation is it becomes significantly slower or even the slightest less accurate, that is a real cost, a serious one.
X = rand(10000);
>> timeit(@() E.^X)
ans =
0.7209758528125
>> timeit(@() exp(X))
ans =
0.2000676988125
And that is a MASSIVE difference in time.
Steven Lord
2020-6-18
James Tursa: this isn't directly related to your idea (which seems like a reasonable enhancement request to file with Support) but FYI if you're computing sin(k*pi) or cos(k*pi) consider using the sinpi or cospi functions introduced in release R2018b.
Stephen23
2020-6-18
编辑:Stephen23
2020-6-18
"Actually, it's likely the opposite"
Not necessarily... two surprisingly common scenarios come to mind:
- users who like to use exist at the start of their script or function to check for optional arguments typically do not check the return value (an observation based on this forum).
- any code which relies on assignin, load, etc. to dynamically create an en variable could quite by interpreted by the MATLAB engine as referring to the function/builtin, e.g.:https://www.mathworks.com/matlabcentral/answers/338434-how-do-i-force-matlab-treat-my-variable-range-as-a-variable-instead-of-a-function
(of course both of these situations should be trivially avoided by writing better code...)
Kareem Elgindy
2020-6-19
Being my first time to post a question on this forum and receive this amount of feedback from various participants has been indeed a very exciting experience to me. This would encourage me to more and more rely on this forum to get nice feedbacks about MATLAB. I’d like to add and clarify a few points in the following:
- When I initially created this post, it was never my intention to replace the exponential function exp(x) with Euler’s number E, or en, etc., for values of x ~= 1. In fact, what I thought of was to use a simple notation like E to call Euler’s number rather than having to type exp(1), which as a mathematician I didn’t like much 😊. What I initially was thinking of was to use a symbol like E, for example, to do simple arithmetic operations on Euler’s number, operations like addition, subtraction, multiplication, and division. I also prefer to type E rather than typing exp(1) to invoke Euler’s number via MATLAB Command Window. If we define a function called E to provide Euler’s number, we can write something like (20*E+63)/(100*E-50) rather than writing (20*exp(1)+63)/(100*exp(1)-50), which doesn’t look much appealing to me as a mathematician. Of course, it would be of greater appealing if I could write (20*e+63)/(100*e-50), which is not possible as e is booked for 10. We can verify that this is fine through the following code:
>> format long; format compact;
E = 2.718281828459045;
(20*E+63)/(100*E-50)
ans =
0.529083523398424
(20*exp(1)+63)/(100*exp(1)-50)
ans =
0.529083523398423
% Using the exact representation of exp(1):
vpa((20*exp(sym(1))+63)/(100*exp(sym(1))-50),16)
ans =
0.5290835233984236
When I created a file and called it E, and put it in MATLAB path, I was curious to learn about the speed of execution, so here is what I had:
>> tic, (20*exp(1)+63)/(100*exp(1)-50), toc
ans =
0.529083523398423
Elapsed time is 0.000561 seconds.
tic, (20*E+63)/(100*E-50), toc
ans =
0.529083523398424
Elapsed time is 0.000346 seconds.
So, calling E was faster than calling exp(1). Of course, this must be true. When I call E I’m calling a constant value already stored, but when I call exp(1) MATLAB would have to calculate the exp function at x=1, which is slower and inconvenient in practice. Why should we evaluate a function at x=1 when its value is already common and known to almost everyone? This is an important subject that I invite MATLAB Development Team to investigate in the future.
- For more accuracy on arithmetic computations involving Euler’s number one can use the same algorithm used by MATLAB for computing exp(1). How MATLAB computes exp(1)? In fact, I don’t know.
- E^x should never replace exp(x), for x~=1. This never crossed my mind when I created this post.
- Generally speaking, any constant when raised to some general power would produce an error in a floating-point system. Consider pi for example and compare it with its exact value when raised to some general power:
>> double(pi^(10+1/10) - sym(pi)^(10+1/10))
ans =
-7.903172385091404e-11
So, it’s not unusual to see a difference between E^x and exp(x), for x~=1. I do support to use exp(x) instead of E^x for general values of x, but I don’t support to write exp(1) instead of E for simple arithmetic operations that only involves E not E^x, for general x values.
- I taught MATLAB training courses for like 10 years now, and each time I teach I receive a few questions from students asking me what is the built-in constant notation for Euler’s number, and they would never become satisfied when I say we use the exponential function exp(1).
- When @John mentioned a list of constants to support his viewpoint, and gave an example on the golden ratio phi = (1 + sqrt(5))/2, I had a feeling from what I read that all the constants he mentioned were easy to compute according to my understanding of what he wrote. I did not make a research on this list but instead I was referring to his examples. So it turns out that one or two, etc. of this list were not easy to compute… this was not the point anyway. The point is, and let me rephrase it given the previous argument: “either MATLAB defines important constants all together, or don't, as some of these constants could easily be calculated using a huge library of valuable built-in functions already written by expert programmers.”
- When @John wrote “suppose the Mathworks were to suddenly introduce a variable with the name en? At that point, ALL legacy code that employs a variable named en that is something else will now potentially start to see bugs.” Correct… But would that mean that MATLAB should now never introduce new built-in functions to avoid conflict with legacy codes! I have to disagree with this opinion. MATLAB should continuously introduce new built-in functions to help researchers do their works with minimal programming efforts. The choice of new names must of course be reasonable and undergoes several checks and smart investigation and revisions before they could be introduced in future releases. Choosing just any new name randomly is a mistake that should be avoided.
- @John: “If you want some named constant, feel free to create it yourself.” Good advice from you. I did 😊. See https://www.mathworks.com/matlabcentral/fileexchange/77046-euler-s-number.
- @John: “e as a named constant in MATLAB will have only one common purpose - to compute e^x”. I largely agree with you on this point. Most well-known applications involving e would include e raised to some power x~=1. But for theoretical purposes this is not a restriction. As I mentioned before, one may do the 4 standard arithmetic operations on e (addition, subtraction, multiplication, and division) conveniently using a nice notation like E, or en, rather than exp(1). Imagine we had a differential equation and we want to solve it, then plot its solution at a large set of data points. Say, the solution of the differential equation was something like exp(1)*sin(x)/10, and we want to plot its values against x=linspace(0,2*pi,10000). Here is what I found when I compared the speed of coding using exp(1) and the simple function en that I created; see https://www.mathworks.com/matlabcentral/fileexchange/77046-euler-s-number:
>> x=linspace(0,2*pi,10000); tic,plot(x,exp(1)*sin(x)/10),toc
Elapsed time is 0.005998 seconds.
x=linspace(0,2*pi,10000); tic,plot(x,en*sin(x)/10),toc
Elapsed time is 0.003541 seconds.
So, oops… en wins the race! There are numerous examples I can give showing that the use of en would be much faster than using exp(1), as long as en is not raised to general powers. This deserves attention from MATLAB Development Team… hopefully they won’t laugh at it.
- @Bjorn: Apparently my second point was misunderstood. My intention, and probably I didn’t phrase my words well enough when I wrote that point, is that calculating Euler's number using the very same method the usual exp(1) is calculated in MATLAB as a built-in function would produce the same accuracy and speed when exp(1) is involved in an operation. I did not intend when I mentioned these words to use E^x though for the reasons stated above. I meant usual arithmetic operations like addition, subtraction, multiplication, and division. Perhaps what caused the confusion was that I started my second point with a sentence that included exp(2.5) and E^2.5. So, I hope now my argument is clearer. To confirm, it never even crossed my mind to replace exp(x) with E^x for x~=1… never since the moment I was born and forever till the moment I die 😊.
- @Steven Lord: “As for pi being necessary, I think students the world around would expect to find pi in MATLAB.” Time for MATLAB Team to think of us as researchers as well. I, as an applied and computational mathematician, need valuable constants to be defined as well. Things like Euler’s number, or the golden ratio, and others would be great to have them all defined in MATLAB. I recall I developed an optimization method during my master studies and the work was published in Applied Mathematics and Computation. In this work I used the golden ratio to locate a minimizer of a function, but unfortunately this significant constant was not defined in FORTRAN—I did the work using FORTRAN back then-- so I had to calculate it and store it in the code. Having a list of important constants arising in various areas well defined in MATLAB can indeed be very convenient and efficient also, because now we can simply invoke them quickly as stored constant values without having to compute them.
- @Steven Lord: “I can ask Cleve if you feel it important though.” Thank you. No need for this. The subject is not about pi; it’s about other important constants that require further attention from MATLAB Development Team. I would be curious though if you could ask Cleve about why Euler’s number and other important constants were never introduced in MATLAB until now, and whether there is any intention to consider this subject in the future.
- To conclude, I’d generally say the following:
- Invoking E to work with is faster than having to calculate exp at x=1.
- I never thought of using E^x instead of exp(x) for x~=1. Not for a single moment. My 2ndpoint I mentioned before was unfortunately misunderstood. But I hope now it’s understood.
- Apparently most, if not all, real-life applications would involve exp(x), for some general power of x~=1. This could be a major reason for neglecting the idea of defining E for exp(1). However, one may still find at least theoretical problems that would involve only E, so using E would be more convenient and faster; see my earlier example on this matter.
- This is a fantastic forum… you made me love MATLAB more and more through your feedbacks and contributions. I used to be an expert of FORTRAN till I started to learn about MATLAB in 2010. I dropped FORTRAN the moment I discovered the beauty of this piece of art called MATLAB. One of the reasons that MATLAB is proud of is having a huge library of built-in functions. This is one of the greatest reasons that attracted me towards this giant software. I hope MATLAB Development Team would someday in the future listen to researchers like me and start defining valuable constants that are common in scientific disciplines and applications to add more and more power to its arsenal of built-in functions and constants.
Best wishes,
Dr. Kareem
David Goodmanson
2020-6-20
编辑:David Goodmanson
2020-6-20
Hello Kareem,
When I made the original suggestion, I was thinking of the 'en' function as something for one's personal toolbox, where you can do anything that seems advantageous. One of the benefits of Matlab. Overall, though, I think there are enough reasons why Matlab will likely not adapt this. But at least you can address objections with regard to speed:
function y = en(x)
if nargin ~= 0
y = exp(x);
else
y = exp(1);
end
end
en % obtain e
ans = 2.7183
en^2 % powers of e
ans = 7.3891
en(1:.001:10) % for speed with a large array
I'm happy enough to use exp(1) instead of an explicit 16 digit number since things are fast enough anyway.
I do think 'en' is a far better choice than E, for a couple of reasons. For the first reason, you have provided the perfect example:
(20*E+63)/(100*E-50)
Here it is way, way too easy to confuse E+63 with the scientific notation 1E+63, same for E-50. The other reason is that with 'en' you don't have to use the caps key. Which means that you won't accidentally hit the ##$%^&@*$! caps lock key and have to backspace out a bunch of stuff, which I do at least once a day..
Stephen23
2020-6-20
@Kareem Elgindy: none of your timing tests have any significance.
The tic documentation clearly states: "Sometimes programs run too fast for tic and toc to provide useful data. If your code is faster than 1/10 second, consider measuring it running in a loop, and then average to find the time for a single run. For more information, see Measure the Performance of Your Code."
This topic has been discussed extensively before, e.g.:
Lets try it. Here are your en FEX submission and exp(1) in two loops:
N = 1e6;
tic
for k = 1:N
A = (20*exp(1)+63)/(100*exp(1)-50);
end
toc
tic
for k = 1:N
B = (20*en+63)/(100*en-50);
end
toc
these are the results:
Elapsed time is 0.170633 seconds. % EXP(1)
Elapsed time is 0.265818 seconds. % your EN
"Of course, this must be true."
Except when it isn't.
Kareem Elgindy
2020-6-20
编辑:Kareem Elgindy
2020-6-20
@David Goodmanson: Thank you for your continuous feedbacks. Your language is extremely polite. You start by addressing people with their names and you never tend to use offensive/mocking words to offend anyone. Thumbs up to you David. I also agree with you that 'en' is a far better choice than E. About the code you described I think it's slower than calling exp(1) because it includes 2 calls to evaluate exp(1): one for en and 1 for exp(1). What I was thinking of was to create a file named say en and use the same technique exercised by MATLAB. Say MATLAB calculates exp(1) using a method called Method A. One can create the file as follows:
function x = en
% Insert Method A below.
end
So now you calculate en using 1 call (in case more accuracy is needed).
@Stephen Cobeldick: Try to put the function exp and en in the same directory and see how it goes. Let MATLAB define en as a built-in function and see how it goes. I don't have to prove it to you that en would work faster. Calling a constant value with a stored value is logically and truly faster than calling a function that involves calculations. This is ABCD common sense! No rational and sensible man on earth can refute this fact even if it hurts some people. Facts do hurt in many cases. I can see one here.
Rik
2020-6-20
With regards to your last point: you are forgetting the JIT compiler. There are some optimizations that are not immediately obvious. Stephen did try it your way, and he found that exp(1) was faster (though not by a lot).
Sometimes it is necessary to test your common sense. And sometimes the world turns out to be counterintuitive.
Another example of strange behavior is that a=[];a(200,200)=0; is a lot faster than a=zeros(200); in several releases (pre-R2015b or something like that). You have to dig into this subject to figure out why that is true, but before doing so I would have expected the first to be slower.
Kareem Elgindy
2020-6-20
编辑:Kareem Elgindy
2020-6-20
@Stephen Cobeldick: As a follow up to my last clarification, you should understand that your example is wrong and in many aspects:
- You are trying to show that a function that requires calculations is faster in practice than a function defined by a stored value!
- When you presented your code you made a huge mistake. You didn't account for function precedence order that MATLAB exercises when it searches/calls a function. Calling a built-in function would generally be faster than calling a user-defined function in large loops, even if the user-defined function was fater than the built-in function-- the reason is simple: MATLAB looks for the built-in function first. So by the time the large loop ends the execution of the operation that requires the built-in function would be relatively smaller than the one for the user-defined function. That's because of the function precedence exercised by MATLAB which is biased to built-in functions I suppose. To verify this point further, I know that variables is probably one of the first things, if not the first, that MATLAB looks for when calling a certain name in the MATLAB Command Window. Before assuming that a name matches a function, MATLAB checks for a variable with that name in the current workspace. So suppose I assign en to a variable called y. Let's check the timing again using your own example:
>> y = en;
>> N = 1e6;
>> tic
for k = 1:N
A = (20*exp(1)+63)/(100*exp(1)-50);
end
toc
tic
for k = 1:N
B = (20*y+63)/(100*y-50);
end
toc
Elapsed time is 0.011791 seconds.
Elapsed time is 0.006986 seconds.
So defining en as a built-in function in MATLAB would kill the function precedence bias and show the true performance of both codes. Any reasonable and fair person would agree with me on this fact.
Kareem Elgindy
2020-6-20
移动:Matt J
2023-7-2
Great feedback @Rik. Could you tell us more about JIT compiler or perhaps pointing out to a simple reference to learn about it quickly? I'm a mathematician not an expert programmer in MATLAB, but trying to improve my skillls and understanding of its features and capabilities. It's good to have you with us today. The example you gave about a=zeros(200) is just stunning. I tested this example in my personal laptop-- I'm using MATLAB 2019b:
>> tic, a=[];a(200,200)=0; toc, tic, a=zeros(200); toc
Elapsed time is 0.000520 seconds.
Elapsed time is 0.000381 seconds.
I was so delighted to learn that common sense wins in this case :-).
Rik
2020-6-20
移动:Matt J
2023-7-2
Except it doesn't. As Stephen mentioned, you shouldn't use tic,toc for code that runs this fast. I also already mentioned that this was the case in older releases.
And about the JIT: I'm not sure where you should start. I seem to recall the documentation discourages optimizing for the JIT, because its behavior could change. I tend to treat it like some sort of caching mechanism (and further encouragement not to use eval and friends).
function foo
fprintf('time elapsed: %.8f\n',timeit(@test1))
fprintf('time elapsed: %.8f\n',timeit(@test2))
end
function test1
a=[];a(200,200)=0;
end
function test2
a=zeros(200);
end
R2015a:
%doens't match common sense
time elapsed: 0.00000604
time elapsed: 0.00001012
R2020a:
%does match common sense
time elapsed: 0.00000949
time elapsed: 0.00000585
Paul
2020-6-20
编辑:Paul
2020-6-20
Kareem,
A couple of times in this thread you've indicated that your desired functionality is important for research or to researchers. Serious question: In what area of research is the actual value of e important, other than in research about properties of the digits of e themselves? And in those areas of research, what is the relevance of using the approximation for e in your FEX function as compared to Matlab's approximation using exp(1)? In other words, if the actual value of e is relevant to your research, of what utility is an approximation limited by a double precision floating point representation?
Stephen23
2020-6-20
编辑:Stephen23
2020-6-23
"You are trying to show that a function that requires calculations is faster in practice than a function defined by a stored value!"
Because sometimes they are.
All other things being equal, I agree completely that a stored value will likely be faster than a calculation. But your timing tests compare inbuilt exp with your own JIT-compiled function, and that is definitely not keeping "all other things equal". A function compiled by the JIT engine is not the same as a precompiled function: for a start it has to be compiled on the fly, and that takes time.
You provided a test comparing apples with oranges, and claimed that the test proved that "So, calling E was faster than calling exp(1). Of course, this must be true." But it isn't. The correct test would be to compare an inbuilt function (with a constant) vs. an inbuilt function (with a calculation), or perhaps two user functions that would both be compiled by the JIT engine. But that is not the test that you presented here: you compared a JIT-compiled function vs an inbuilt function, and clearly their runtimes are not so simple to compare.
The only point I made in my previous comment was that the timings less than 1/10 second are unreliable, exactly as the documentation states. I did not make any statements about what those functions are doing.
"When you presented your code you made a huge mistake. You didn't account for function precedence order that MATLAB exercises when it searches/calls a function"
The function precedence order depends significantly upon the folder where the file is saved (information that I actually did not give in my last comment). The MATLAB documentation describes the function precedence order here:
The relevant categories given on that page are:
"1. Variables"
...
"10. Functions in the current folder"
"11. Functions elsewhere on the path, in order of appearance... Built-in function ..."
I saved your en file in the current folder (category 10), so it actually had a higher precendence than the builtin exp function (category 11). The word "built" is only used once on that entire page, in category 11.
"Calling a built-in function would generally be faster than calling a user-defined function in large loops, even if the user-defined function was fater than the built-in function-- the reason is simple: MATLAB looks for the built-in function first."
Actually MATLAB follows the function precedence order given in the documentation that I linked to above: a user-defined function saved in the current directory (or a private directory, etc.) will be found before a built-in function that is anywhere else on the Search Path. And of course this will not make any difference to the runtime of the function, just a very tiny difference to the time it takes MATLAB to find the function, which once compiled by the JIT engine is likely not repeated for each function call.
Steven Lord
2020-6-20
In theory, having a function that doesn't need to do any calculations and just return a constant value will be faster than one that needs to do calculations.
In practice, neither is going to be the bottleneck in your code. If it is, I suspect getting that value is all your code is doing.
You could submit this enhancement request to Technical Support using the telephone icon in the upper-right corner of this page. But I'll be honest with you. I know how much it costs to add even the most basic built-in function to MATLAB. That cost is higher than you think it is. [As one example, exp is supported for use with MATLAB Coder and GPU Coder. For parity in functionality, e would need to be supported in code generation as well. That would require at the least testing it in code generation to ensure it works.] Would the benefit of this change (letting users type e instead of exp(1) in their code) outweight the cost to implement and maintain this function? In my opinion, it would not.
You asked a reasonable question, and I think it spawned some interesting discussion, but I'm doubtful that enhancement request would be actioned. Of course there's nothing wrong with writing your own e.m function that returns that constant value. Would it be as fast as if that function were built into MATLAB? Probably not. Would you notice the difference? Probably not.
Kareem Elgindy
2020-6-23
@Paul: Hello Paul and many thanks for sharing your comment with us in this forum. You asked two important questions. As for the first question, think of any mathematical model in which one or more of its terms, or perhaps the solution to the model involves an expression like sin(exp(1)*x)+3*exp(1), and we need to compute this expression for a certain range of x-values. Why should we ask MATLAB to calculate the exponential function twice at x=1, when we could easily define exp(1) as a constant, say en, and type sin(en*x)+3*en. This would be faster and computationally cost efficient indeed. Consider the following example:
>> format long; format compact
x=linspace(1,2,4); sin(exp(1)*x)+3*exp(1)
ans =
8.565626775880046 7.690599490173445 7.171347209837022 7.405799017154221
>> sin(en*x)+3*en
ans =
8.565626775880045 7.690599490173443 7.171347209837021 7.405799017154219
>> vpa(sin(exp(sym(1))*x)+3*exp(sym(1)),16)
ans =
[ 8.565626775880044, 7.690599490173443, 7.171347209837021, 7.405799017154219]
Of course, if one needs more accuracy than possibly 15 or 16 significant digits, we can then ask MATLAB to evaluate the exp function at x=1—it’s funny though to see that en gave a better accuracy than exp(1) in the above example. So exp was called and computed twice at x=1, at least theoretically took longer for execution, and yet gave a poorer result. On the other hand, en included ZERO computations and gave a better result!
As for your second question, I, as an applied and computational mathematician, never used more than 16 significant digits in all my previous works (which includes solving ODEs, PDES, integral equations, integro-differential equations, nonlinear optimization, and optimal control theory) except when I wanted to compare my approximations with the exact values of the solution—I personally prefer to use MATHEMATICA to do symbolic computations than MATLAB though.
Kareem Elgindy
2020-6-23
@Steven Lord: Thank you for sharing your comments. I'm happy that we share the common viewpoint that a function that doesn't need to do any calculations and just return a constant value will be faster than one that needs to do calculations, at least theoretically. I believe though that if we play a fair game and we neutralize all other factors that could influence the speed of execution of both files, then definitely en wins in speed. For double-precision floating point arithmetic widely common for numerical computations, en is sufficient and very practical to my research needs.
I believe it remains important to ask: why should we evaluate exp at x=1 when e is a very known value? In almost all algorithms I developed in my career so far, I frequently use constant parameter inputs defined as double-precision numbers, i.e. are represented by 16 significant digits. In double-precision floating-point systems, this is typically the case. So why should we ask MATLAB to compute exp at x=1 when we can use its 16 significant digits representation instead. This would be faster and computationally more efficient. How about other important constants like the golden ratio which does not occur redundant with other functions? Why should we calculate them when their values are very known values? One of the reasons MATLAB Developers are proud of is that they have a huge library of functions that can help programmers and users to do certain tasks with minimal programming efforts, but they fail to have even a decent library for important mathematical constants. If they define these constants, we could use them directly in our works without having to calculate them using other functions or formulas.
Your suggestion to submit this enhancement request to Technical Support shows that you are an open minded person and I'm so glad that I'm having this conversation with you. Thanks also for your sincere information about the cost and your expert feedback.
David Goodmanson
2020-6-23
Hello Kareem,
as long as we are on the subject of accuracy, is there a reason why in your file exchage contribution you used
x = 2.718281828459045
instead of
x = 2.718281828459046
which is the result obtained by rounding a more precise expression to 15 decimal places?
Kareem Elgindy
2020-6-27
编辑:Kareem Elgindy
2020-6-27
Hi David,
This is a nice remark. When we invoke exp(1) and en in MATLAB we get
>> exp(1)
ans =
2.718281828459046
>> en
ans =
2.718281828459045
You referred to the value of exp(1) here as being `a more precise expression to 15 decimal places'. Surprisingly, it isn't! To verify this matter, let us check using multiple resources:
- If you check Wikipedia at https://en.wikipedia.org/wiki/E_(mathematical_constant), you'll see there that, and I'm quoting, 'The numerical value of e truncated to 50 decimal places is 2.71828182845904523536028747135266249775724709369995...'
- If you are interested to see the digits representation of Euler's number to 10,000 digits, see https://www.math.utah.edu/~pa/math/e.html.
- I used MATHEMATICA to display the digits of Euler's number to 21 digits precision and here's what I discovered
- If we display Euler's number to 16 accurate significant digits using MATLAB symbolic toolbox we get
>> vpa(exp(sym(1)),16)
ans =
2.718281828459045
which is the same value obtained by en. From the above arguments, you can understand now that it's in fact more accurate to use en instead of exp(1) in double-precision floating point systems. You can add this as another advantage of using en.
Hope this answers your question.
Best wishes,
Dr. Kareem
David Goodmanson
2020-6-27
编辑:David Goodmanson
2020-6-27
Hi Kareem,
you are correct. I rather expected that vpa(exp(1),25) would give the right result and was going with that, but
vpa(exp(1),25)
ans = 2.718281828459045534884808
^
whereas
vpa(exp(sym(1)),25)
ans = 2.718281828459045235360287
is correct.
Jan
2023-7-5
What an epic discussion. Some levels less sophisticated:
I needed exp(1) in a line of code called very frequently. exp() is an expensive function, such that a locally defined constant is efficient:
N = 1e6;
tic
for k = 1:N
A = (20 * exp(1) + 63) / (100 * exp(1) - 50);
end
toc
Elapsed time is 0.017215 seconds.
tic
for k = 1:N
B = (20 * en + 63) / (100 * en - 50);
end
toc
Elapsed time is 6.074733 seconds.
tic
exp1 = exp(1);
for k = 1:N
B = (20 * exp1 + 63) / (100 * exp1 - 50);
end
toc
Elapsed time is 0.006386 seconds.
function y = en(x)
if nargin ~= 0
y = exp(x);
else
y = exp(1);
end
end
14 个评论
James Tursa
2023-7-5
编辑:James Tursa
2023-7-6
Observations on exp(1) ...
Online MATLAB:
exp(1) - double(exp(sym(1)))
ans = 0
MATLAB R2021a PCWIN:
>> exp(1) - double(exp(sym(1)))
ans =
4.4409e-16
Of course you don't expect that whatever method is used in the background for exp( ) to always produce the closest approximation for every possible input value, so no real issue with the discrepancy above. It is just interesting that my PC version of MATLAB doesn't produce the closest double precision value to e using exp(1). It would in fact be more consistent to just hard code this particular value directly if you are using it in such arithmetic expressions as above, e.g.,
exp1 = 2.718281828459045;
exp1 - double(exp(sym(1)))
ans = 0
*** EDIT ***
A quick follow up. Neither of these values for e gets recognized by the sym engine for what they are. E.g.,
MATLAB Online:
exp1 = exp(1)
exp1 = 2.7183
e = 2.718281828459045
e = 2.7183
num2hex(exp1)
ans = '4005bf0a8b145769'
num2hex(e)
ans = '4005bf0a8b145769'
sym(exp1) % <-- doesn't recognize this as exp(1)
ans =
sym(e)
ans =
MATLAB R2021a PCWIN:
>> exp1 = exp(1)
exp1 =
2.718281828459046
>> e = 2.718281828459045
e =
2.718281828459045
>> num2hex(exp1)
ans =
'4005bf0a8b14576a' <-- one bit different from below
>> num2hex(e)
ans =
'4005bf0a8b145769' <-- one bit different from above
>> sym(exp1)
ans =
3060513257434037/1125899906842624 <-- doesn't recognize exp1 as exp(1)
>> sym(e)
ans =
6121026514868073/2251799813685248 <-- doesn't recognize e as exp(1)
>> sym(pi)
ans =
pi <-- but it does recognize pi
Paul
2023-7-5
编辑:Paul
2023-7-6
Malab 2022a PCWIN:
>> exp(1) - double(exp(sym(1)))
ans =
0
Edit:
I'm not sure of the totality of what you're tyring to illusrate. But I'm not surprised that sym(exp(1)) is not recognized as the symbolic constant e. That would be done by
exp(sym(1))
ans =
e
If sym(exp(1)) returned the symbolic constant e, then there may be problem if, by intent or not, the input to sym is a double that is equal in value to exp(1) but not intended to be e.
Also, the interpreter knows that sym(pi) is to be the symbolic constant pi (if the symbol pi is not overwritten to mean something else).
sym(pi)
ans =
π
Having said that, I'm kind of (maybe even very) surprised that the following yields the symbolic constant pi
p = pi;
class(p)
ans = 'double'
sym(p)
ans =
π
Steven Lord
2023-7-6
The sym function with its default conversion technique (see the section on that documentation page discussing the flag input argument) recognizes floating-point numbers in certain forms and compensates for round-off error. For modest-sized integers p and q, it identifies numbers that were (likely) generated by expressions of the form p*pi/q and returns numbers in that form. In the case of pi, p and q are both 1 which is a modest-sized integer and so it represents pi as π. But exp(p) is not one of the forms that conversion technique recognizes.
James Tursa
2023-7-6
编辑:James Tursa
2023-7-6
@Paul If I understand your latest comment correctly, I think you are misinterpreting what sym(pi) is doing. In this form, the pi( ) function is called first and returns a double precision value. This double precision value is then passed on to the sym( ) function. The sym( ) function then examines the passed in value to determine if it can discern your intent (looking for modest rational values or rational values times π). This all happens inside the sym( ) function and it has no clue how this floating point number was initially generated. This is not a result of the parser seeing the sym(pi) form and somehow constructing a symbolic π variable because it saw the letters pi and discerned your intent. After all, how could the parser know that the pi( ) function hasn't been changed and doesn't actually return the π value? So starting with p=pi first makes no difference in how this value gets passed into sym( ). The result depends on the value, not on the syntax used to generate the value. To illustrate:
sym(pi)
ans =
π
pi = 5
pi = 5
sym(pi)
ans =
5
sym(acos(-1))
ans =
π
sym(atan(1))
ans =
Also this comment you made:
"If sym(exp(1)) returned the symbolic constant e, then there may be problem if, by intent or not, the input to sym is a double that is equal in value to exp(1) but not intended to be e."
In fact, that is exactly what happens with pi. The intent is discerned based solely on the value passed in, not on something the parser recognized in the calling syntax. So your comment applies to the exact situation we have with pi currently, but I don't see any significant issue with that.
I have never had the need for the sym( ) function to recognize any forms of (p/q)*exp(r/s) etc., so it doesn't really bother me that this isn't part of sym( ) capability. The only reason I included that in this thread is because I was curious if either of the "close" numbers to e would be recognized by the sym( ) function.
@Steven Lord Something weird happened FYI. When I first ran the code above, the sym(pi) generated 3.1415. I had to run the code a second time to get the π result. But I can't reproduce this. Very strange ...
John D'Errico
2023-7-9
Note that when I want the true mathematical constant, I can (still) use sym like this:
sym('pi')
ans =
π
But to get e, you could use str2sym, or you could do
exp(sym(1))
ans =
e
as opposed to
sym(exp(1))
ans =
which of course fails.
Paul
2023-7-9
As of a few releases ago, sym('pi') is not the same as sym(pi).
x1 = sym(pi)
x1 =
π
x2 = sym('pi')
x2 =
π
symType([x1 x2])
ans = 1×2 string array
"constant" "variable"
cos([x1 x2])
ans =
Inside the symbolic engine, the thing that x2 references isn't recognized as the constant pi, but is just a plain variable that happens to be named pi.
Paul
2023-7-9
编辑:Paul
2023-7-9
Running here on Answers, I'm occasionally seeing this result in the display of x1. It seems to show up randomly.
x1 = sym(pi)
x1 =
3.1416
sympref('FloatingPointOutput')
ans = logical
1
Somehow the FloatingPointOutput of sympref is getting changed from its default value of false.
James Tursa
2023-7-10
编辑:James Tursa
2023-7-10
@Paul Wow ... I never knew that about sym('pi'). This turns out to be the case for my R2021a PCWIN version:
>> sym('pi')
ans =
pi
>> sym(pi)
ans =
pi
>> sym('pi') - sym(pi)
ans =
pi - pi
>> simplify(ans)
ans =
pi - pi
>> double(sym('pi'))
Error using symengine
Unable to convert expression containing symbolic variables into double array. Apply 'subs' function first to
substitute values for variables.
Error in sym/double (line 709)
Xstr = mupadmex('symobj::double', S.s, 0);
>> double(sym(pi))
ans =
3.14159265358979
>> acos(sym(-1)) - sym(pi)
ans =
0
Talk about confusing! I will never use sym('pi') again ...
Paul
2023-7-10
I don't really ever use sym('pi'). But, I can see how it might be nice for formatting equations with trig functions or complex exponentials with the symbol pi, instead of having Matlab automatically evaluate those terms (when it can).
Using the symbolic constant
sympref('FloatingPointOutput',false); % force to avoid the problems observed upthread
Pi = sym(pi);
we get
x = cos(Pi/3) + cos(Pi/11)
x =
y = exp(-1j*Pi) + 1 == 0
y =
Using the sympolic variable
Pi = sym('pi');
we get
x = cos(Pi/3) + cos(Pi/11)
x =
y = exp(-1j*Pi) + 1 == 0
y =
which might be a nicer form for display or document preparation.
If needed, then sub in the symbolic constant for simplification/evaluation
subs(x,Pi,sym(pi))
ans =
subs(y,Pi,sym(pi))
ans =
Steven Lord
2023-7-10
The meaning of sym('pi') changed in release R2020a. The fact that it displays in the Live Editor (or in MATLAB Answers) as πinstead of something like the word pi seems confusing, I've reported that to the development staff.
James Tursa
2023-7-10
编辑:James Tursa
2023-7-10
@Paul I can see your formatting argument for display etc. purposes. +1
sym('pi') + sym('phi') + sym('gamma') + sym('alpha') + sym('beta')
ans =
The uppercase versions work with the first letter capitalized:
sym('Pi') + sym('Phi') + sym('Gamma') + sym('Delta') + sym('Sigma')
ans =
But not if all the letters are capitalized:
sym('PI') + sym('PHI') + sym('GAMMA') + sym('ALPHA') + sym('BETA')
ans =
I keep learning new stuff in this forum ...
Walter Roberson
2023-7-10
I had reported to Mathworks some inconsistencies in the handling of symbolic π . Minor issues that I thought would be easily fixed. Instead Mathworks choose to make sym('pi') into just a plain variable that did not indicate the constant, breaking years of common use. I'm still a bit bummed out about it. I feel it is ineligent and error-prone to count on sym(pi) recognizing that the input value is "close enough" to π and converting that to the constant
sympref('floatingpoint', false)
ans = logical
1
X = pi - 1e-14;
X - pi
ans = -1.0214e-14
sym(X)
ans =
π
delta = (1:100)*1e-15;
X = sym(pi - delta);
mask = find(X == sym(pi));
maxdelta = delta(max(mask))
maxdelta = 6.9000e-14
so anything closer than roughly 69e-15 to pi is counted as-if it is π
maxdelta / eps(pi)
ans = 155.3742
which is roughly 155 times eps -- it is not a matter of "aliasing", Mathworks has deliberately permitted "slop" to be considered "close enough" to match.
Paul
2023-7-10
Having the symbolic variable sym('pi') display as π does have its uses and is consistent with how other symbolic variables are displayed as shown in this comment and this comment. If a change really is warranted in how sym('pi') is displayed, maybe it should be a sympref.
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Performance and Memory 的更多信息
产品
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!发生错误
由于页面发生更改,无法完成操作。请重新加载页面以查看其更新后的状态。
您也可以从以下列表中选择网站:
如何获得最佳网站性能
选择中国网站(中文或英文)以获得最佳网站性能。其他 MathWorks 国家/地区网站并未针对您所在位置的访问进行优化。
美洲
- América Latina (Español)
- Canada (English)
- United States (English)
欧洲
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom(English)
亚太
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)