Jekyll2020-09-22T18:50:05+00:00https://hugogranstrom.com/feed.xmlHugo Granström - Math, Phyics and Nim/Python BlogMy Nim/Python programming, math and physics blogHugo GranströmMath Codified - Derivatives2018-12-08T00:00:00+00:002018-12-08T00:00:00+00:00https://hugogranstrom.com/math-codified-derivatives<p>This equation is probably somewhat familiar to most people who have studied a bit of calculus: \(f'(x) = \lim_{h \to 0}\frac{f(x+h)-f(x)}{h}\). Today we are breaking it down and converting it to code to really see how this works, when the math notation has been stripped off.</p>
<p>To start with, how do we calculate the gradient (slope) of a function? We take the difference in y divided by the difference in x: \(\frac{\Delta y}{\Delta x} = \frac{y_2-y_1}{x_2-x_1} = \frac{f(x_2)-f(x_1)}{x_2-x_1}\)</p>
<p>If our function is a straight line this will work no matter which \(x_2\) and \(x_1\) we choose (as long as \(x_2 > x_1\), otherwise we get the wrong sign). If our function instead for example is a quadratic equation, we will not get the the gradient in a point, but the average gradient in a segment of the function. The smaller we make the distance between \(x_2\) and \(x_1\) the better of an approximation it will be for the function’s gradient at a certain point. This is where the \(\lim_{h \to 0}\) comes in. \(h\) is the difference between \(x_2\) and \(x_1\) and when it approaches \(0\) the result becomes the gradient at a single point \(x\). The reason we only have a \(h\) in the denominator is because the x’s cancel out: \((x+h)-x = h\).</p>
<p>Now to the part you probably came here to read. Translating this math expression to a piece of code-cake:</p>
<p>Let’s first create a python function for our math-function. I choose the equation \(f(x)=x^2\)</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
<span class="k">return</span> <span class="n">x</span><span class="o">**</span><span class="mi">2</span>
</code></pre></div></div>
<p>Next let’s define h, the very small difference between \(x_2\) and \(x_1\). We can’t set it to 0 because we can’t divide by 0. So we choose a very small number instead, namely \(h = 10^{-6}\):</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">h</span> <span class="o">=</span> <span class="mi">10</span><span class="o">**-</span><span class="mi">6</span>
</code></pre></div></div>
<p>Now we have the \(\lim_{h \to 0}\) and f(x) part sorted. Now it’s time to define our python representation of \(f(x)'\):</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">derivative</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
<span class="n">x2</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">h</span>
<span class="n">y2</span> <span class="o">=</span> <span class="n">f</span><span class="p">(</span><span class="n">x2</span><span class="p">)</span>
<span class="n">x1</span> <span class="o">=</span> <span class="n">x</span>
<span class="n">y1</span> <span class="o">=</span> <span class="n">f</span><span class="p">(</span><span class="n">x1</span><span class="p">)</span>
<span class="n">gradient</span> <span class="o">=</span> <span class="p">(</span><span class="n">y2</span> <span class="o">-</span> <span class="n">y1</span><span class="p">)</span><span class="o">/</span><span class="p">(</span><span class="n">h</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">gradient</span><span class="p">)</span>
<span class="k">return</span> <span class="n">gradient</span>
</code></pre></div></div>
<p>If we test to call the derivative function with a x-value we can check if it work. The derivative function of \(x^2\) is \(2x\):</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">derivative</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="c1"># returns 4.0000010006480125
</span></code></pre></div></div>
<p>The actual value is 4 but this is a pretty good approximation I would say (it’s first at the 6’th decimal it gets it wrong). To get even more accurate results, choose a smaller \(h\).</p>
<h2 id="how-to-choose-a-good-h">How to choose a good \(h\)?</h2>
<p>You may think that if you choose a really really small \(h\) like \(10^{-100}\) that you would get a super good approximation of the derivative. That would have been really nice but sadly normal computers can’t handle extremely small numbers at the same time as it handles large one. For example has Python no problems handling \(10^{-100}\) on it’s own put if you add it to \(1\) it is too small comparatively:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">print</span><span class="p">(</span><span class="mf">1e-100</span><span class="p">)</span> <span class="c1"># same as 1 * 10 ** -100
# prints: 1e-100
</span><span class="k">print</span><span class="p">(</span><span class="mi">1</span> <span class="o">+</span> <span class="mf">1e-100</span><span class="p">)</span>
<span class="c1"># prints: 1.0
</span></code></pre></div></div>
<p>The reason for this is that computers save numbers with limited precision. Just like we for example can’t write \(1/3 = 0.3333333333...\) the entire decimal expansion on paper your computer can’t save all numbers exactly. The smallest number you can have between to two numbers is called machine epsilon and is denoted \(\epsilon_M\). On a 64-bit computer a float (double precision to be more exact) has a \(\epsilon_M \approx 2.2 * 10^{-16}\). If you want to get the machine epsilon on your machine using Python you can get it with numpy:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="n">np</span>
<span class="n">eps</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">finfo</span><span class="p">(</span><span class="nb">float</span><span class="p">).</span><span class="n">eps</span>
</code></pre></div></div>
<p>Now you may wonder why I have brought this up, what does it have to do with choosing a good \(h\)? The answer to that question is that we don’t want our h to be too close to \(\epsilon_M\) because then our computer won’t be able to see a difference between \(f(x+h)\) and \(f(x)\) (remember what the definition of \(\epsilon_M\) was?) and then \(f(x+h)-f(x) = 0\) which we don’t want. So how are we supposed to choose \(h\) then, what is small enough to get a good approximation while not being to close to \(\epsilon_M\).</p>
<p>\(h = \sqrt{\epsilon_M} * x\) happens to be a good choice. Here \(x\) is the x-value we want to evaluate the derivative of f(x) at. This works when \(x \neq 0\) because then \(h = 0\) which is problematic. We will have to add a check for that in our function. In Python we can modify our derivate function:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="n">np</span>
<span class="k">def</span> <span class="nf">derivative</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
<span class="k">if</span> <span class="n">x</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">eps</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">finfo</span><span class="p">(</span><span class="nb">float</span><span class="p">).</span><span class="n">eps</span>
<span class="n">h</span> <span class="o">=</span> <span class="n">eps</span><span class="o">**</span><span class="mf">0.5</span> <span class="o">*</span> <span class="n">x</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">h</span> <span class="o">=</span> <span class="mf">1e-6</span>
<span class="n">x2</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">h</span>
<span class="n">y2</span> <span class="o">=</span> <span class="n">f</span><span class="p">(</span><span class="n">x2</span><span class="p">)</span>
<span class="n">x1</span> <span class="o">=</span> <span class="n">x</span>
<span class="n">y1</span> <span class="o">=</span> <span class="n">f</span><span class="p">(</span><span class="n">x1</span><span class="p">)</span>
<span class="n">gradient</span> <span class="o">=</span> <span class="p">(</span><span class="n">y2</span> <span class="o">-</span> <span class="n">y1</span><span class="p">)</span><span class="o">/</span><span class="p">(</span><span class="n">h</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">gradient</span><span class="p">)</span>
<span class="k">return</span> <span class="n">gradient</span>
</code></pre></div></div>
<p>Now our function chooses an appropriate \(h\) by itself. Cool, right!?</p>
<h2 id="are-there-more-accurate-methods">Are there more accurate methods?</h2>
<p>This is a question you may ask yourself. Are there any other, better ways to calculate the derivative of a function? The answer is: Yes there are! Instead of calculating the value of the function in \(x\) and \(x+h\) we now calculate it in \(x-h\) and \(x+h\). This gives a \(h = (x+h) - (x-h) = 2h\). The formula becomes:
\(f'(x) = \frac{f(x+h) - f(x-h)}{2h}\). It doesn’t look that different from our old formula but it is actually more accurate. If we write it in Python using everything we have learned so far:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="n">np</span>
<span class="k">def</span> <span class="nf">cool_function</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
<span class="k">return</span> <span class="n">np</span><span class="p">.</span><span class="n">sin</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">exp</span><span class="p">(</span><span class="n">x</span><span class="p">))</span> <span class="c1"># f(x) = sin(e^x)
</span>
<span class="k">def</span> <span class="nf">derivative</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">x</span><span class="p">):</span>
<span class="k">if</span> <span class="n">x</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">eps</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">finfo</span><span class="p">(</span><span class="nb">float</span><span class="p">).</span><span class="n">eps</span>
<span class="n">h</span> <span class="o">=</span> <span class="n">eps</span><span class="o">**</span><span class="mf">0.5</span> <span class="o">*</span> <span class="n">x</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">h</span> <span class="o">=</span> <span class="mf">1e-6</span>
<span class="n">x1</span> <span class="o">=</span> <span class="n">x</span> <span class="o">-</span> <span class="n">h</span>
<span class="n">x2</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">h</span>
<span class="n">y1</span> <span class="o">=</span> <span class="n">f</span><span class="p">(</span><span class="n">x1</span><span class="p">)</span>
<span class="n">y2</span> <span class="o">=</span> <span class="n">f</span><span class="p">(</span><span class="n">x2</span><span class="p">)</span>
<span class="n">gradient</span> <span class="o">=</span> <span class="p">(</span><span class="n">y2</span> <span class="o">-</span> <span class="n">y1</span><span class="p">)</span><span class="o">/</span><span class="p">(</span><span class="mi">2</span><span class="o">*</span><span class="n">h</span><span class="p">)</span>
<span class="k">return</span> <span class="n">gradient</span>
</code></pre></div></div>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">derivative</span><span class="p">(</span><span class="n">cool_function</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span> <span class="c1"># calculate the derivative of cool_function in x=3
# returns: 6.600002091377974
</span></code></pre></div></div>
<p>The correct value is roughly 6.60000209300594833 so it’s a really good approximation. Our first method give the approximation 6.599993718167146 which isn’t far off either but it’s still 3 orders of magnitude less accurate than our second method.</p>
<p>It still begs the question: are there even more accurate methods? The answer is: Yes! But I won’t cover them in this article. I will leave you with one of them though, and it’s up to you to implement it in Python:</p>
\[f'(x) = \frac{-f(x + 2h) + 8f(x+h) - 8f(x-h) + f(x-2h)}{12h}\]
<p>(Note: that this method appears to be more accurate then the previous one when \(h\) is bigger then \(10^{-6}\). When it becomes smaller the inaccuracy becomes larger because we are adding more rounding errors together then we are in the others)</p>
<p>That was it. I hope you enjoyed this and learned something new. My hope is that if you have experience in programming but you didn’t fully understand derivatives in school, that this article helped you grasp it better.</p>Hugo GranströmThis equation is probably somewhat familiar to most people who have studied a bit of calculus: \(f'(x) = \lim_{h \to 0}\frac{f(x+h)-f(x)}{h}\). Today we are breaking it down and converting it to code to really see how this works, when the math notation has been stripped off.Showing that 0.999… = 1 using geometric sums2018-07-31T00:00:00+00:002018-07-31T00:00:00+00:00https://hugogranstrom.com/0.999-equals-1<p>If you have browsed a forum where math is discussed, it is likely you have seen people claiming both that \(0.999... = 1\) and \(0.999... \neq 1\). Today I will show you that the first one is correct using geometric sums. You don’t need to take my word for it, you will be able to prove it yourself.</p>
<h2 id="geometric-sums">Geometric Sums</h2>
<p>“What is a geometric sum?”, you may ask. Keep calm, I will get you covered. A geometric sum is a sum where the first term is a number, let’s call it \(a_1\) and the second term is a constant, \(k\), times the first term, so \(a_1*k\). The third term is the second term times the same constant so it becomes \(a_1*k*k = a_1*k^2\). And then it continues like that for as long as we want to calculate the sum. If we want to calculate the sum of the first 5 terms the last one would be \(a_1*k^4\) because the first term don’t have a \(k\) in it. Generally the last term thus becomes \(a_1*k^{n-1}\) if we want to take the sum of the \(n\) first terms. A geometric sum is of the form:</p>
\[S_n = a_1 + a_1*k + a_1*k^2 + a_1*k^3 + a_1*k^4 + ... + a_1*k^{n-2} + a_1*k^{n-1}\]
<p>Here \(S_n\) stands for “the sum of the \(n\) first terms”. The terms are quite similar so it isn’t to farfetched to think that there is a formula to calculate the the sum given only \(a_1\), \(k\) and \(n\). There is in fact a formula but I won’t just give it to you, we will derive it ourself to have a stable foundation for our argument.</p>
<h2 id="deriving-the-formula-for-a-geometric-sum">Deriving the formula for a Geometric Sum</h2>
<p>We start out with the equation for a general geometric sum:</p>
\[S_n = a_1 + a_1*k + a_1*k^2 + a_1*k^3 + a_1*k^4 + ... + a_1*k^{n-2} + a_1*k^{n-1}\]
<p>Then we multiply both sides by \(k\):</p>
\[k*S_n = a_1*k + a_1*k^2 + a_1*k^3 + a_1*k^4 + a_1*k^5 + ... + a_1*k^{n-1} + a_1*k^n\]
<p>The reason we did this is because now we can see that the right side of the equation is nearly the same as it was before except \(a_1\) is missing and we have a new term, \(a_1*k^n\). We can then utilize that fact to rewrite the equation like this:</p>
\[k*S_n = S_n + a_1*k^n - a_1\]
<p>This is much neater, right? Now all we have to do is to solve for \(S_n\). We start by subtracting \(S_n\) from both sides:</p>
\[k*S_n - S_n = a_1*k^n - a_1\]
<p>Then we factor both sides by them self:</p>
\[S_n(k - 1) = a_1(k^n - 1)\]
<p>Dividing by \((k-1)\) will give us our formula:</p>
\[S_n = a_1 \frac{k^n - 1}{k - 1}\]
<p>There we have it, a simple formula for calculating a geometric sum.</p>
<h2 id="lets-tackle-the-question">Let’s tackle the question</h2>
<p>I said we would show that \(0.999... = 1\) so let’s cut to the action. First what does \(0.999...\) really mean? In this context it means that the pattern shown will continue forever. In other words that there is an infinite amount of 9’s after the decimal sign. Just a quick reflection here: Is there any real number between 1 and 0.999…? Independent of your answer, what implications would that have? Think about it, and experiment. That’s how new mathematics are invented, people playing around with the rules of math. “What happens if I ignore that?” and “How would this work if it was like this” are questions reasonable to wonder about. Complex numbers (they are as real as the real numbers, not imaginary in any way) were found this way, when someone thought “What if negative numbers have a square root” and just rolled along.</p>
<p>Must have been an uneven cut because we seems to have sidetracked a bit from the action. 0.999… can if we separate every digit into a 9 times a power of a 10th be written as:</p>
\[0 + 9 \frac{1}{10} + 9 \frac{1}{10^2} + 9 \frac{1}{10^3} ...\]
<p>This looks looks like a geometric sum, who could have guessed? \(a_1\) in this case is \(9\frac{1}{10}\), \(k\) is \(\frac{1}{10}\) and \(n\) is \(\infty\). We have a slight problem here: \(n\) is \(\infty\). Let’s see how our formula handles that.</p>
\[S_n = a_1 \frac{k^n - 1}{k - 1}\]
<p>If \(k\) is larger than or equal to 1, then the sum diverges and it doesn’t have a defined sum. If on the other hand \(k < 1\), then the sum converges. We can in fact simplify the formula when <strong>both</strong> \(n = \infty\) <strong>and</strong> \(k < 1\) because \(k^n\) then becomes 0 at the limit:</p>
\[lim_{n\to\infty} a_1\frac{k^n-1}{k-1} = a_1\frac{0-1}{k-1} = \frac{-a_1}{k-1} = \frac{-a_1}{-(1-k)} = \frac{a_1}{1-k}\]
<p>There we have a really nice and simple formula. It is quite remarkable that we can calculate something that has an infinite component using such a simple and beautiful formula. If we now insert our values into it we get:</p>
\[\frac{a_1}{1-k} = \frac{\frac{9}{10}}{1-\frac{1}{10}} = \frac{\frac{9}{10}}{\frac{9}{10}} = 1\]
<p>There we have it! We have showed that \(0.999... = 1\) using a geometric sum. If someone ever tells you that it isn’t true, prove it to them yourself. You have all the tools you need for that now.</p>
<p>Can you come up with any other “debate-able” sequence of decimals that can be proven to be something using geometric sums? If you do, please let me know in the comments. Have a nice day and remember that the human fantasy is limitless (but not undefined).</p>Hugo GranströmIf you have browsed a forum where math is discussed, it is likely you have seen people claiming both that \(0.999... = 1\) and \(0.999... \neq 1\). Today I will show you that the first one is correct using geometric sums. You don’t need to take my word for it, you will be able to prove it yourself.Making sense of the Monty Hall Problem2018-07-30T00:00:00+00:002018-07-30T00:00:00+00:00https://hugogranstrom.com/making-sense-monty-hall<p>The Monty Hall problem is a quiet famous problem where most people’s intuition are wrong. There are many variations of it but I will use one with playing card. It goes like this:</p>
<p><em>You and a friend sit at a table opposite of each other. On the table there are three faced down playing cards, one king and two knights. Your friend knows which card is which but you have no idea. The ultimate goal in this game is to figure out which card is the king. First you get to choose one of the cards, and you tell your friend which. He/She then flips one of the other card two cards and it is a knight. You are now offered to stay with the card you chose at first or to switch to the second faced down card. Which of these choices has the greatest probability of you picking the king?</em></p>
<p>Most people unfamiliar with this problem will probably say: “It doesn’t matter. They are equally likely”. We will here in a few different ways show that it does in fact matter if you switch or stay.</p>
<p>First let’s try a more obvious example. Instead of three card, we have ten, nine knights and one king. You choose a card like before but instead of flipping just one knight, your friend flips 8 knights. Now there remains just two faced down cards, your first choice and one other. The key here is that you always have just two cards in the end to choose from. Would you switch or would you stay? Here your intuition probably tells you to switch because there is a greater probability that the card you chose was a knight than a king. In fact there is just 1/10 probability that you chose the king as your first card and thus a 9/10 probability that any of the other cards are the king. Therefore you have a 9/10 probability to pick the king if you switch card because you know that 8 of the other cards are not the king. Are you on board? If not, think through this example one more time and remember the key: we are always left with just two cards in the end to choose from.</p>
<p>If we lower the amount of cards to nine, would it still be better to switch most of the time? Yes, you would have a 8/9 probability of picking the king if you switched. The same holds for 8, 7, 6, 5, 4 and 3 cards as well. Let’s look a little closer on the case of 4 cards. When you first choose a card you have 1/4 probability of picking the king. When you are left with just two card to choose from, the probability that you chose the king is still just 1/4 and therefore there must be a 3/4 probability that the other card is the king. We are nearly there now! Time for 3 cards: You have 1/3 probability of choosing the king and therefore a 2/3 probability that you did not choose the king. When one of the other cards are flipped and shown to be a knight, the probability still remains. You are more likely to have missed the king than to have picked it at first and therefore switching is the better option. In the case of 3 cards, you have a 2/3 probability to pick the king if you switch.</p>
<p>Now a more mathy way to attack the problem (keep calm, we won’t hurt it). Is there any probability that remains the same throughout the whole problem, both mathematically and intuition-wise? One such probability I think is the probability that we did NOT choose the king as our first card, <strong>P(not king)</strong>. This probability is 2/3 and it will not change during the game. The game goes as before but we pause when the knight has been flipped. The probability is still the same that we did NOT choose the king at first and therefore it is still just 1/3 that the card we chose is a king but it is 2/3 that any of the other card are the king. Now we also know that one of those cards are not the king and therefore the other card must have the probability 2/3 of being king. Switching cards therefore gives you a 2/3 chance to pick the king.</p>
<p>If this article didn’t make you understand the Monty Hall Problem then I recommend <a href="https://www.youtube.com/watch?v=4Lb-6rxZxx0">this</a> and <a href="https://www.youtube.com/watch?v=7u6kFlWZOWg">this</a> Youtube videos by a channel called Numberphile which explains this with pictures as well. They are by the way a really interesting channel for people interested in math.</p>
<p>Have a nice day!</p>Hugo GranströmThe Monty Hall problem is a quiet famous problem where most people’s intuition are wrong. There are many variations of it but I will use one with playing card. It goes like this:Gravity Simulator2018-07-21T00:00:00+00:002018-07-21T00:00:00+00:00https://hugogranstrom.com/gravity-simulator<p>This is a gravity simulator I have written in python using the library VPython/Glowscript. This project was inspired by an exercise my math teacher gave us where we were supposed to simulate the moon’s orbit around the earth in excel using differential equations.</p>
<p>Luckily there exists better tools for this, like python in conjunction with VPython where you get both vectors and graphics. So no need for splitting the vectors in an X-part and an Y-part, that is really convenient actually. My first intention was to just write the earth-moon simulation but then I thought: “Why not do the entire solar system instead”. And so I did, the Sun, the eight planets and Pluto (you will forever be a planet to me) all dancing together in a cosmic dance. Futhermore, I chose to use the Euler method for integration because it is easy to implement and it is the one most people are familiar with. This simulation won’t be near accurate enough to simulate the actual solar system anyway (for example relativity is not accounted for and the timestep is too big) so the inaccuracy doesn’t bother me. I just want to see some planets dance… and throw in a black hole later. I have also chosen to use other units then the SI-units: distance is measured in AU (average distance between earth and the sun), time is measured in days and mass in solar masses. This is because then the computer doesn’t have to handle such large numbers and hence it consumes less memory. A consequence of this is that G, the gravitational constant changes it’s values from the familiar 6.67e-11 to 2.959e-04. The size of the planets are scaled up by a factor of 1000 to make them visible. Otherwise are all the distances correct. The initial positions and velocities are real data from June 2018 from <a href="https://ssd.jpl.nasa.gov/horizons.cgi">here</a>. Watch it and have fun!</p>
<p>The source code can be found on Glowscript <a href="http://www.glowscript.org/#/user/hajenzoo/folder/Public/program/gravity-simulator">here</a> (click “View this program” to see the source code)</p>
<p>The simulation with a black hole can be found <a href="http://www.glowscript.org/#/user/hajenzoo/folder/Public/program/gravity-simulator-black-hole">here</a> (click “Run this program” in the upper left corner to start it)</p>
<p>A tutorial on how to code this yourself will be coming in the future. I the meanwhile if you’re interested, I have written comments in the code that may be helpful.</p>
<p>Remember, you can always count on your best friend, the calculator!</p>
<p>A heads up: running this simulation can drain quite a lot of power so if you’re on a laptop, I recommend that you have your charger plugged in while running this.</p>
<p>Controls:</p>
<ul>
<li>Zoom: scroll</li>
<li>Pan: Hold SHIFT and drag with left mouse button</li>
<li>Rotate: Hold and drag right mouse button</li>
</ul>
<p>Thanks to @marsater for ideas and feedback for this project.</p>
<div id="glowscript" class="glowscript">
<script type="text/javascript" src="https://s3.amazonaws.com/glowscript/lib/jquery/2.1/jquery.min.js"></script>
<script type="text/javascript" src="https://s3.amazonaws.com/glowscript/lib/jquery/2.1/jquery-ui.custom.min.js"></script>
<script type="text/javascript" src="https://s3.amazonaws.com/glowscript/package/glow.2.7.min.js"></script>
<script type="text/javascript" src="https://s3.amazonaws.com/glowscript/package/RSrun.2.7.min.js"></script>
<script type="text/javascript"><!--//--><![CDATA[//><!--
;(function() { var __rt=srequire('streamline/lib/callbacks/runtime').runtime(__filename, false),__func=__rt.__func,__cb=__rt.__cb; var RS_modules = {};
RS_modules.pythonize = {};
(function() {
function strings() {
var string_funcs, exclude, name;
string_funcs = set("capitalize strip lstrip rstrip islower isupper isspace lower upper swapcase center count endswith startswith find rfind index rindex format join ljust rjust partition rpartition replace split rsplit splitlines zfill".split(" "));
if (!arguments.length) {
exclude = (function() {
var s = RS_set();
s.jsset.add("split");
s.jsset.add("replace");
return s;
})(); }
else if (arguments[0]) {
exclude = Array.prototype.slice.call(arguments); }
else {
exclude = null; } ;
if (exclude) {
string_funcs = string_funcs.difference(set(exclude)); } ;
var RS_Iter0 = RS_Iterable(string_funcs);
for (var RS_Index0 = 0; RS_Index0["<"](RS_Iter0.length); RS_Index0++) {
name = RS_Iter0[RS_Index0];
(RS_expr_temp = String.prototype)[((((typeof name === "number") && name["<"](0))) ? RS_expr_temp.length["+"](name) : name)] = (RS_expr_temp = RS_str.prototype)[((((typeof name === "number") && name["<"](0))) ? RS_expr_temp.length["+"](name) : name)]; }; }; RS_modules.pythonize.strings = strings;
})();
function main(_) { var version, box, sphere, cylinder, pyramid, cone, helix, ellipsoid, ring, arrow, compound, display, vector, print, scene, RS_ls, G, dt, time, scale_factor, AU, M, bodies, sun, earth, mercury, venus, mars, jupiter, saturn, uranus, neptune, pluto, time_label, body, __name__, strings, RS_Iter4, RS_Index4, RS_Iter5, RS_Index5, __this = this;
function Body() {
if ((this.RS_object_id === undefined)) { Object.defineProperty(this, "RS_object_id", { value: ++RS_object_counter }); };
Body.prototype.__init__.apply(this, arguments); }; var __frame = { name: "main", line: 32 }; return __func(_, this, arguments, main, 0, __frame, function __$main() { version = RS_list_decorate(["2.7","glowscript",]); Array.prototype["+"] = function(r) { return this.concat(r); }; Array.prototype["*"] = function(r) { return __array_times_number(this, r); }; __name__ = "__main__"; window.__GSlang = "vpython"; box = vp_box; sphere = vp_sphere; cylinder = vp_cylinder; pyramid = vp_pyramid; cone = vp_cone; helix = vp_helix; ellipsoid = vp_ellipsoid; ring = vp_ring; arrow = vp_arrow; compound = vp_compound; display = canvas; vector = vec; print = GSprint; scene = canvas(); strings = RS_modules.pythonize.strings; strings(); "8"; G = 0.00029592; "9"; dt = 0.01; "10"; time = 0; "11"; scale_factor = 1000; "12"; AU = 150000000000; "13"; M = 2e+30; "16"; bodies = RS_list_decorate([]); "18";
Body.prototype.__init__ = function __init__() {
var self = this;
var mass = ((((arguments[0] === undefined) || (((((0 === arguments.length["-"](1)) && (arguments[arguments.length["-"](1)] !== null)) && (typeof arguments[arguments.length["-"](1)] === "object")) && (arguments[arguments.length["-"](1)][RS_kwargs_symbol] === true))))) ? __init__.__defaults__.mass : arguments[0]);
var radius = ((((arguments[1] === undefined) || (((((1 === arguments.length["-"](1)) && (arguments[arguments.length["-"](1)] !== null)) && (typeof arguments[arguments.length["-"](1)] === "object")) && (arguments[arguments.length["-"](1)][RS_kwargs_symbol] === true))))) ? __init__.__defaults__.radius : arguments[1]);
var velocity = ((((arguments[2] === undefined) || (((((2 === arguments.length["-"](1)) && (arguments[arguments.length["-"](1)] !== null)) && (typeof arguments[arguments.length["-"](1)] === "object")) && (arguments[arguments.length["-"](1)][RS_kwargs_symbol] === true))))) ? __init__.__defaults__.velocity : arguments[2]);
var position = ((((arguments[3] === undefined) || (((((3 === arguments.length["-"](1)) && (arguments[arguments.length["-"](1)] !== null)) && (typeof arguments[arguments.length["-"](1)] === "object")) && (arguments[arguments.length["-"](1)][RS_kwargs_symbol] === true))))) ? __init__.__defaults__.position : arguments[3]);
var color = ((((arguments[4] === undefined) || (((((4 === arguments.length["-"](1)) && (arguments[arguments.length["-"](1)] !== null)) && (typeof arguments[arguments.length["-"](1)] === "object")) && (arguments[arguments.length["-"](1)][RS_kwargs_symbol] === true))))) ? __init__.__defaults__.color : arguments[4]);
var trail = ((((arguments[5] === undefined) || (((((5 === arguments.length["-"](1)) && (arguments[arguments.length["-"](1)] !== null)) && (typeof arguments[arguments.length["-"](1)] === "object")) && (arguments[arguments.length["-"](1)][RS_kwargs_symbol] === true))))) ? __init__.__defaults__.trail : arguments[5]);
var name = ((((arguments[6] === undefined) || (((((6 === arguments.length["-"](1)) && (arguments[arguments.length["-"](1)] !== null)) && (typeof arguments[arguments.length["-"](1)] === "object")) && (arguments[arguments.length["-"](1)][RS_kwargs_symbol] === true))))) ? __init__.__defaults__.name : arguments[6]);
var RS_kwargs_obj = arguments[arguments.length["-"](1)];
if ((((RS_kwargs_obj === null) || (typeof RS_kwargs_obj !== "object")) || (RS_kwargs_obj[RS_kwargs_symbol] !== true))) { RS_kwargs_obj = { }; };
if (Object.prototype.hasOwnProperty.call(RS_kwargs_obj, "mass")) {
mass = RS_kwargs_obj.mass; } ;
if (Object.prototype.hasOwnProperty.call(RS_kwargs_obj, "radius")) {
radius = RS_kwargs_obj.radius; } ;
if (Object.prototype.hasOwnProperty.call(RS_kwargs_obj, "velocity")) {
velocity = RS_kwargs_obj.velocity; } ;
if (Object.prototype.hasOwnProperty.call(RS_kwargs_obj, "position")) {
position = RS_kwargs_obj.position; } ;
if (Object.prototype.hasOwnProperty.call(RS_kwargs_obj, "color")) {
color = RS_kwargs_obj.color; } ;
if (Object.prototype.hasOwnProperty.call(RS_kwargs_obj, "trail")) {
trail = RS_kwargs_obj.trail; } ;
if (Object.prototype.hasOwnProperty.call(RS_kwargs_obj, "name")) {
name = RS_kwargs_obj.name; } ;
var RS_ls;
"20";
self.mass = mass;
"21";
self.velocity = velocity;
"22";
self.position = position;
"23";
self.color = color;
"24";
self.radius = radius;
"25";
self.forces = RS_list_decorate([]);
"26";
self.acc = vector(0, 0, 0);
"27";
self.sum_force = vector(0, 0, 0);
"28";
self.name = name;
"29";
self.label = RS_interpolate_kwargs.call(this, label, [RS_desugar_kwargs({ pos: self.position, text: self.name, height: 10 }),]);
"30";
self.sphere = RS_interpolate_kwargs.call(this, sphere, [RS_desugar_kwargs({ pos: self.position, color: self.color, radius: self.radius["*"](scale_factor), make_trail: trail, retain: 300 }),]);
"31";
bodies.append(self); };
if (!Body.prototype.__init__.__defaults__) { Object.defineProperties(Body.prototype.__init__, {
__defaults__: { value: { mass: 1, radius: 1, velocity: vector(0, 0, 0), position: vector(0, 0, 0), color: color.white, trail: true, name: "Body" } },
__handles_kwarg_interpolation__: { value: true },
__argnames__: { value: ["mass","radius","velocity","position","color","trail","name",] } }); } ;
Body.__argnames__ = Body.prototype.__init__.__argnames__;
Body.__handles_kwarg_interpolation__ = Body.prototype.__init__.__handles_kwarg_interpolation__;
Body.prototype.update = function update() {
var self = this;
var RS_ls, force;
"33";
self.forces = RS_list_decorate([]);
"34";
self.sum_force = vector(0, 0, 0);
"35";
self.gravitational_force();
"39";
var RS_Iter1 = RS_Iterable(self.forces);
for (var RS_Index1 = 0; RS_Index1["<"](RS_Iter1.length); RS_Index1++) {
force = RS_Iter1[RS_Index1];
"40";
self.sum_force = self.sum_force["+="](force); };
"43";
self.acc = self.sum_force["/"](self.mass);
"44";
self.velocity = self.velocity["+="](dt["*"](self.acc)); };
Body.prototype.move = function move() {
var self = this;
var RS_ls;
"47";
self.position = self.position["+="](dt["*"](self.velocity));
"50";
self.sphere.pos = self.position;
"51";
self.label.pos = self.position; };
Body.prototype.gravitational_force = function gravitational_force() {
var self = this;
var RS_ls, r, force, dir, body;
"55";
var RS_Iter2 = RS_Iterable(bodies);
for (var RS_Index2 = 0; RS_Index2["<"](RS_Iter2.length); RS_Index2++) {
body = RS_Iter2[RS_Index2];
"57";
r = mag(self.position["-"](body.position));
"59";
if (r["<"](self.radius["+"](body.radius))) {
"60";
continue; } ;
"62";
force = G["*"](self.mass)["*"](body.mass)["/"](GS_power(r, 2));
"64";
dir = norm(body.position["-"](self.position));
"66";
force = force["*"](dir);
"68";
self.forces.append(force); }; };
Body.prototype.updateVerlet = function updateVerlet() {
var self = this;
var RS_ls, force;
"72";
self.forces = RS_list_decorate([]);
"73";
self.sum_force = vector(0, 0, 0);
"74";
self.gravitational_force();
"78";
var RS_Iter3 = RS_Iterable(self.forces);
for (var RS_Index3 = 0; RS_Index3["<"](RS_Iter3.length); RS_Index3++) {
force = RS_Iter3[RS_Index3];
"79";
self.sum_force = self.sum_force["+="](force); };
"82";
self.position = self.position["+="](self.velocity["*"](dt)["+"](self.acc["/"](2)["*"](GS_power(dt, 2))));
"83";
self.velocity = self.velocity["+="](dt["/"](2)["*"](self.acc["+"](self.sum_force["/"](self.mass))));
"84";
self.acc = self.sum_force["/"](self.mass);
"86";
self.sphere.pos = self.position;
"87";
self.label.pos = self.position; };
Body.prototype.__repr__ = function __repr__() {
return "<"["+"](__name__)["+"](".")["+"](this.constructor.name)["+"](" #")["+"](this.RS_object_id)["+"](">"); };
Body.prototype.__str__ = function __str__() {
return this.__repr_; };
Object.defineProperty(Body.prototype, "__bases__", { value: [] });
Body.prototype.RS_ls = "19";
Body.prototype.RS_ls = "32";
Body.prototype.RS_ls = "46";
Body.prototype.RS_ls = "53";
Body.prototype.RS_ls = "71";
"92";
sun = RS_interpolate_kwargs_constructor.call(Object.create(Body.prototype), false, Body, [RS_desugar_kwargs({ mass: 1, radius: 700000000["*"](5)["/"](scale_factor)["/"](AU), color: color.yellow, trail: false, name: "Sun" }),]);
"100";
earth = RS_interpolate_kwargs_constructor.call(Object.create(Body.prototype), false, Body, [RS_desugar_kwargs({ mass: 6e+24["/"](M), radius: 6371000["/"](AU), position: vector(0.5111702950987252["-u"](), 0.8734341386147972["-u"](), 0.00003902531498407046), velocity: vector(0.01457401965494037, 0.008749957786090569["-u"](), 3.393201214360642e-7["-u"]()), color: color.green, name: "Earth" }),]);
"111";
mercury = RS_interpolate_kwargs_constructor.call(Object.create(Body.prototype), false, Body, [RS_desugar_kwargs({ mass: earth.mass["*"](0.055), radius: 6000000["/"](AU), position: vector(0.360006238731298, 0.08310671431721671["-u"](), 0.03981766501010686["-u"]()), velocity: vector(0.0008732371820239134, 0.0286750815794258, 0.002263026727476856), color: color.red, name: "Mercury" }),]);
"123";
venus = RS_interpolate_kwargs_constructor.call(Object.create(Body.prototype), false, Body, [RS_desugar_kwargs({ mass: earth.mass["*"](0.815), radius: 6000000["/"](AU), position: vector(0.5460148756311848["-u"](), 0.4654289630909307, 0.03789319798488837), velocity: vector(0.01319751648139675["-u"](), 0.01549708277964608["-u"](), 0.0005490020542624818), color: color.white, name: "Venus" }),]);
"135";
mars = RS_interpolate_kwargs_constructor.call(Object.create(Body.prototype), false, Body, [RS_desugar_kwargs({ mass: earth.mass["*"](0.107), radius: 6000000["/"](AU), velocity: vector(0.01444719742599419, 0.0002365918534978303["-u"](), 0.000359488561244826["-u"]()), position: vector(0.1508529480814324["-u"](), 1.460121856503524["-u"](), 0.02689190873994556["-u"]()), color: color.red, name: "Mars" }),]);
"145";
jupiter = RS_interpolate_kwargs_constructor.call(Object.create(Body.prototype), false, Body, [RS_desugar_kwargs({ mass: earth.mass["*"](318), radius: 70000000["/"](AU), velocity: vector(0.005611682808441865, 0.004596785105938998["-u"](), 0.0001064356940327842["-u"]()), position: vector(3.545075313382027["-u"](), 4.081361865858232["-u"](), 0.09627457319753692), color: color.blue, name: "Jupiter" }),]);
"155";
saturn = RS_interpolate_kwargs_constructor.call(Object.create(Body.prototype), false, Body, [RS_desugar_kwargs({ mass: earth.mass["*"](95), radius: 60000000["/"](AU), velocity: vector(0.005262021976694793, 0.0004141890616120753, 0.0002169327374705523["-u"]()), position: vector(0.7842529344684837, 10.03393486265119["-u"](), 0.1431896871358062), color: color.white, name: "Saturn" }),]);
"165";
uranus = RS_interpolate_kwargs_constructor.call(Object.create(Body.prototype), false, Body, [RS_desugar_kwargs({ mass: earth.mass["*"](14), radius: 25000000["/"](AU), velocity: vector(0.0019052013493924["-u"](), 0.003265505721711341, 0.000036690734434005), position: vector(17.46114323983198, 9.517430938519276, 0.1907513002050031["-u"]()), color: color.blue, name: "Uranus" }),]);
"175";
neptune = RS_interpolate_kwargs_constructor.call(Object.create(Body.prototype), false, Body, [RS_desugar_kwargs({ mass: earth.mass["*"](17), radius: 24000000["/"](AU), velocity: vector(0.0008427417626787077, 0.003035037625808767, 0.00008199842541642128["-u"]()), position: vector(28.80079206580985, 8.17390036348871["-u"](), 0.495478418972816["-u"]()), color: color.yellow, name: "Neptune" }),]);
"185";
pluto = RS_interpolate_kwargs_constructor.call(Object.create(Body.prototype), false, Body, [RS_desugar_kwargs({ mass: earth.mass["*"](0.0022), radius: 1000000["/"](AU), position: vector(11.20198708794019, 31.64123744663468["-u"](), 0.1446313453325374), velocity: vector(0.003029567845289497, 0.0003743167934314588, 0.000926069693706297["-u"]()), color: color.yellow, name: "Pluto" }),]);
"213";
time_label = RS_interpolate_kwargs.call(__this, label, [RS_desugar_kwargs({ pos: vector(75, 350, 0), pixel_pos: true, text: "Time: "["+"](str(time["/"](365)))["+"](" years") }),]);
"216"; return (function ___(__break) { var __more; var __loop = __cb(_, __frame, 0, 0, function __$main() { __more = false;
var __1 = true; if (__1) {
"217";
return rate(5000, __cb(_, __frame, 228, 8, function __$main() {
"219";
RS_Iter4 = RS_Iterable(bodies);
for (RS_Index4 = 0; RS_Index4["<"](RS_Iter4.length); RS_Index4++) {
body = RS_Iter4[RS_Index4];
"220";
body.update(); };
"222";
RS_Iter5 = RS_Iterable(bodies);
for (RS_Index5 = 0; RS_Index5["<"](RS_Iter5.length); RS_Index5++) {
body = RS_Iter5[RS_Index5];
"223";
body.move(); };
"224";
time_label.text = "Time: {:.2f} years".format(time["/"](365));
"225";
time = time["+="](dt); while (__more) { __loop(); }; __more = true; }, true)); } else { __break(); } ; }); do { __loop(); } while (__more); __more = true; })(_); });};
if (!main.__argnames__) { Object.defineProperties(main, {
__argnames__: { value: ["_",] } });};
;$(function(){ window.__context = { glowscript_container: $("#glowscript").removeAttr("id") }; main(__func) })})()
//--><!]]></script>
</div>Hugo GranströmThis is a gravity simulator I have written in python using the library VPython/Glowscript. This project was inspired by an exercise my math teacher gave us where we were supposed to simulate the moon’s orbit around the earth in excel using differential equations.Math Codified - Limits2018-07-12T00:00:00+00:002018-07-12T00:00:00+00:00https://hugogranstrom.com/math-codified-limits<h3 id="prerequisites">Prerequisites</h3>
<ul>
<li>I assume you have a basic understanding of python and math.</li>
<li>I will be using python 3.6 and above (sorry no legacy code here).</li>
<li>I recommend writing the code yourself (in a jupyter notebook perhaps) and to play around with it.</li>
<li>Being prepared for bad jokes</li>
</ul>
<h3 id="basics">Basics</h3>
<p>Limits are a concept in math used in various situations, for example when calculating derivatives. I have a article about how to understand derivatives using python <a href="https://hugogranstrom.com/math-codified-derivatives/">here</a>.</p>
<p>Limits are used when a function \(f(x)\) isn’t defined for a certain input \(x\) or if we want to see if the function has a limit at \(+\infty\) or \(-\infty\) ie if the function converges at infinity (functions can also converge to other functions but that is a matter for another day). That a function converges means that there is a number that the function approaches at \(\infty\), an invisible line it never crosses. Often it can be seen as a “ceiling” or a “floor” like in this picture:</p>
<p><img src="https://hugogranstrom.com/images/2018-07/floor1.png" alt="Floor function" /></p>
<p>A limit is written as this:</p>
\[\lim_{x \to a} f(x)\]
<p>\(\lim\) stands for <em>limes</em> in latin but I always think of it as standing for the english word <em>limit</em>, so if you hear someone talk about <em>limes</em> they are probably talking about limits. \(f(x)\) is the function we want to get the limit of and \(a\) is the limit we want \(x\) to approach. We write \(x \to a\) to say “as \(x\) approaches \(a\)”. The whole expression if spoken would be <em>The limit of \(f(x)\) as \(x\) approaches \(a\)</em>.</p>
<p>Can we with that in mind evaluate some limits of the function in the picture above, \(f(x) = \frac{1}{x} + 2\)? <strong>Let’s try!</strong></p>
<p>First let’s explore what happens when \(x\) becomes really big, namely when \(x\) approaches infinity. We would write the expression like this:</p>
\[\lim_{x \to \infty} f(x) = \lim_{x \to \infty} \frac{1}{x} + 2\]
<p>If we study the graph we can see that the function never seems to go lower than the red-dashed line at \(y=2\), in other words the limit as x approaches \(\infty\) is 2 or as a math expression:</p>
\[\lim_{x \to \infty} \frac{1}{x} + 2 = 2\]
<p>When you just look at the equation that makes alot of sense as well, \(\frac{1}{x}\) becomes really small when \(x\) is large so it basically becomes \(0 + 2\) at \(\infty\).</p>
<p>A quick note about when to use limits and when not to. If you have a well behaved function (defined everywhere basically) then the limit is just the function evaluated at that point:</p>
\[\lim_{ x \to a } f(x) = f(x)\]
<p>It is just when a function isn’t defined for certain \(x\) (or if you want to see how it behaves at \(\infty\)) that limits are useful. We will show this in an code example below.</p>
<h3 id="exercise">Exercise</h3>
<p>That wasn’t too hard, right? Here comes an exercise for you to test yourself (the answer is at the bottom of this page):</p>
<p>Write a mathematical expression of the limit of \(\lim_{x \to \infty} \frac{1}{x} + 2\) as \(x\) approaches \(0\) and write a reasonable answer to that limit.</p>
<h1 id="code-time">Code Time!</h1>
<p>Now comes the juicy part you came here for! Put on your coding gear, here we GO! (don’t tell me you haven’t got any coding gear, let’s see… I know, take that old hoodie and… a pair of glasses! That looks rather code-ish, right?)</p>
<p>The way we are going to do limits in python is when \(a\) is a number we will add a small number \(h\) to it and evaluate an approximation of the value like this:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># our function. is the same as above
</span><span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
<span class="k">return</span> <span class="mi">1</span><span class="o">/</span><span class="n">x</span> <span class="o">+</span> <span class="mi">2</span>
<span class="c1"># the small number we will add to x.
</span><span class="n">h</span> <span class="o">=</span> <span class="mf">1e-3</span>
<span class="c1"># The limit as x goes to 0
</span><span class="n">x</span> <span class="o">=</span> <span class="mi">0</span> <span class="o">+</span> <span class="n">h</span>
<span class="n">limit</span> <span class="o">=</span> <span class="n">f</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">limit</span><span class="p">)</span>
<span class="c1"># 1002.0
</span></code></pre></div></div>
<p>Note: 1e-3 is scientfic notation for \(1 \times 10^{-3}\) and likewise is 7e3 the same as \(7 \times 10^{3}\).</p>
<p>If we test with a smaller \(h\), for example 1e-6, we get 1000002. This is a strong indication that it tends to infinity and if we choose even smaller values for \(h\) the limits get’s higher and higher. We can modify the code to write the answer for multiple values of \(h\) and that could help us see a trend:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
<span class="k">return</span> <span class="mi">1</span><span class="o">/</span><span class="n">x</span> <span class="o">+</span> <span class="mi">2</span>
<span class="n">x</span> <span class="o">=</span> <span class="mi">0</span>
<span class="c1"># a list of the h's we want to test
</span><span class="n">h_list</span> <span class="o">=</span> <span class="p">[</span><span class="mf">1e-3</span><span class="p">,</span> <span class="mf">1e-6</span><span class="p">,</span> <span class="mf">1e-9</span><span class="p">,</span> <span class="mf">1e-12</span><span class="p">]</span>
<span class="c1"># loop over the h's and evaluate the function at each
</span><span class="k">for</span> <span class="n">h</span> <span class="ow">in</span> <span class="n">h_list</span><span class="p">:</span>
<span class="n">limit</span> <span class="o">=</span> <span class="n">f</span><span class="p">(</span><span class="n">x</span> <span class="o">+</span> <span class="n">h</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">f"h: </span><span class="si">{</span><span class="n">h</span><span class="si">}</span><span class="s">, limit: </span><span class="si">{</span><span class="n">limit</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="c1">#h: 0.001, limit: 1002.0
#h: 1e-06, limit: 1000002.0
#h: 1e-09, limit: 1000000001.9999999
#h: 1e-12, limit: 1000000000002.0
</span></code></pre></div></div>
<p>This is the structure we will be using now when we want to see how a function behaves as it approaches infinity. We will have a list of increasingly big numbers (instead of small):</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
<span class="k">return</span> <span class="mi">1</span><span class="o">/</span><span class="n">x</span> <span class="o">+</span> <span class="mi">2</span>
<span class="c1"># list of big numbers
</span><span class="n">x_list</span> <span class="o">=</span> <span class="p">[</span><span class="mf">1e3</span><span class="p">,</span> <span class="mf">1e6</span><span class="p">,</span> <span class="mf">1e9</span><span class="p">,</span> <span class="mf">1e12</span><span class="p">]</span>
<span class="c1"># loop over the x's and evaluate the function at each
</span><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">x_list</span><span class="p">:</span>
<span class="n">limit</span> <span class="o">=</span> <span class="n">f</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">f"x: </span><span class="si">{</span><span class="n">x</span><span class="si">}</span><span class="s">, limit: </span><span class="si">{</span><span class="n">limit</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="c1">#x: 1000.0, limit: 2.001
#x: 1000000.0, limit: 2.000001
#x: 1000000000.0, limit: 2.000000001
#x: 1000000000000.0, limit: 2.000000000001
</span></code></pre></div></div>
<p>As we can see it seems to converge to 2 at infinity. If you continue to increase \(x\) you will soon surpass the precision of floating point numbers (that is shown) and it will just display “2.0”. Python is really convinient in the way that you can have really big numbers without worrying about what whether it should be an <em>unsigned</em>, <em>long</em> etc <em>int</em>. It just works! Test to print some really big number, preferably using the notation I have used above if you don’t want to hold the 0-button until the heat-death of the universe. It will handle quite big numbers, numbers to0 big for us to even imagine. 1e100, \(10^{100}\) also called a <em>googol</em> would need to divided by 2 one hundred times just to get down to \(10^{70}\). Think about how big \(2^{100}\) is, even so it is just \(\frac{1}{10^{68}}\) % of a googol. A googol was probably a piece of cake for your computer, then I have a challenge for it: beware! The <em>googolplex</em> ! (the space after the word is to keep the size of the number down, in <em>fact</em> it would be so ridiculously huge that I don’t know how to write it in any other way then that). A <em>googolplex</em> is 10 to the power of a googol, \(10^{10^{100}}\). Seeing as my computer can’t handle numbers larger than 1e300 I have a hard time seeing a computer being able to handle a googolplex without cheating. For anyone interested, a <em>googol</em> is about a <em>googol</em>-th (\(\frac{1}{10^{98}}\)%) of a percent of a <em>googolplex</em>.</p>
<p>If you are reading this at night I apologize for the last paragraph, it might have been a bit to math heavy for this article about codifying math. But I just think that it is remarkable that we can express really big numbers even though we can’t really comprehend them.</p>
<p>That was it for this time, I hope you learnt at least something new and that I haven’t scared you away from math. I would really like to discuss math and such with you so if you are in the mood you can find me on <a href="https://twitter.com/GranstromHugo">twitter</a> and on my email which both can be found in the footer.</p>
<p><strong>Have a nice day!</strong></p>
<h3 id="answer-to-exercise">Answer to Exercise</h3>
\[\lim_{ x \to 0 } \frac{1}{x} + 2 = \infty\]
<p>An important note here is differentiate between \(\lim_{ x \to 0 } \frac{1}{x} + 2 = \infty\) and \(\frac{1}{0} + 2 = \infty\). The first one is true but the second one is not, this is correct then:
\(\frac{1}{0} + 2\) <em>is undefined</em>.</p>
<h3 id="questions--contact">Questions & Contact</h3>
<p>If you got any questions comment them below, send me an email or contact me on twitter. The links are in the footer below. You can also contact me there casually just to discuss what’s at the <em>limit</em> of your imagination right now.</p>Hugo GranströmLimits are a concept in math used in various situations, for example when calculating derivatives. Limits are used when a function f(x) isn't defined for a certain input x or if we want to see if the function has a limit at infinity.Hello World!2018-05-06T00:00:00+00:002018-05-06T00:00:00+00:00https://hugogranstrom.com/hello-world<p>Hello World!</p>
<p>This is my first blog post here. I’m a science student in Sweden who is interested in mathematics and programming.
My programming language of choice is Python, mainly because I think Java (my first language) and the others look too cluttered with their overuse of curly brackets {}.</p>
<p>Here is the line of code most of us had as our first computer program:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">print</span><span class="p">(</span><span class="s">"Hello World!"</span><span class="p">)</span>
</code></pre></div></div>
<p>Ahh… What nostalgia! My memories come back from when I was 13 and coded Java on my 4 inch android phone with “Hacker’s Keyboard”. Though that time it was a more complicated expression I had to write…..</p>Hugo GranströmHello World!