MATLAB Answers

Why Euler's number e = 2.71828... is not a built-in constant in MATLAB?

167 views (last 30 days)
Kareem Elgindy
Kareem Elgindy on 17 Jun 2020
Edited: David Goodmanson on 27 Jun 2020
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?

  13 Comments

Kareem Elgindy
Kareem Elgindy on 18 Jun 2020
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.

Sign in to comment.

Answers (2)

John D'Errico
John D'Errico on 18 Jun 2020
Edited: John D'Errico on 18 Jun 2020
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.

  25 Comments

David Goodmanson
David Goodmanson on 23 Jun 2020
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
Kareem Elgindy on 27 Jun 2020
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:
  1. 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...'
  2. 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.
  3. I used MATHEMATICA to display the digits of Euler's number to 21 digits precision and here's what I discovered
  4. 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
David Goodmanson on 27 Jun 2020
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.

Sign in to comment.


Kareem Elgindy
Kareem Elgindy on 20 Jun 2020
Edited: Kareem Elgindy on 20 Jun 2020
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 :-).

  2 Comments

Rik
Rik on 20 Jun 2020
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

Sign in to comment.

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!