{"id":5060,"date":"2019-08-30T19:36:21","date_gmt":"2019-08-31T00:36:21","guid":{"rendered":"https:\/\/justinparrtech.com\/JustinParr-Tech\/?p=5060"},"modified":"2019-09-01T12:54:28","modified_gmt":"2019-09-01T17:54:28","slug":"programming-tip-turn-floating-point-operations-in-to-integer-operations","status":"publish","type":"post","link":"https:\/\/justinparrtech.com\/JustinParr-Tech\/programming-tip-turn-floating-point-operations-in-to-integer-operations\/","title":{"rendered":"Pro(gramming) Tip:  Turn Floating Point Operations in to Integer Operations"},"content":{"rendered":"<p>Or, why floating point operations are slow, and how to avoid them.<\/p>\n<p><!--more--><\/p>\n<p>&nbsp;<\/p>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_81 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\"><p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<\/div><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/justinparrtech.com\/JustinParr-Tech\/programming-tip-turn-floating-point-operations-in-to-integer-operations\/#a-brief-note-on-notation\" >A Brief Note on Notation<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/justinparrtech.com\/JustinParr-Tech\/programming-tip-turn-floating-point-operations-in-to-integer-operations\/#quick-recap-of-integers\" >Quick Recap of Integers<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/justinparrtech.com\/JustinParr-Tech\/programming-tip-turn-floating-point-operations-in-to-integer-operations\/#what-is-a-floating-point\" >What is a Floating Point?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/justinparrtech.com\/JustinParr-Tech\/programming-tip-turn-floating-point-operations-in-to-integer-operations\/#inside-the-computer\" >Inside the Computer<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/justinparrtech.com\/JustinParr-Tech\/programming-tip-turn-floating-point-operations-in-to-integer-operations\/#integer-math\" >Integer Math<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/justinparrtech.com\/JustinParr-Tech\/programming-tip-turn-floating-point-operations-in-to-integer-operations\/#floating-point-math\" >Floating Point Math<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/justinparrtech.com\/JustinParr-Tech\/programming-tip-turn-floating-point-operations-in-to-integer-operations\/#comparing-floats-to-ints\" >Comparing Floats to Ints<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/justinparrtech.com\/JustinParr-Tech\/programming-tip-turn-floating-point-operations-in-to-integer-operations\/#how-to-convert-operations-to-integer-only-pt-1-%e2%80%93-beginner-mode\" >How to Convert Operations to Integer-Only, Pt 1 &#8211; Beginner Mode<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/justinparrtech.com\/JustinParr-Tech\/programming-tip-turn-floating-point-operations-in-to-integer-operations\/#how-to-convert-operations-to-integer-only-pt-2-%e2%80%93-expert-mode\" >How to Convert Operations to Integer-Only, Pt 2 &#8211; Expert Mode<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/justinparrtech.com\/JustinParr-Tech\/programming-tip-turn-floating-point-operations-in-to-integer-operations\/#how-to-convert-operations-to-integer-only-pt-3-%e2%80%93-super-advanced-mode\" >How to Convert Operations to Integer-Only, Pt 3 &#8211; Super Advanced Mode<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/justinparrtech.com\/JustinParr-Tech\/programming-tip-turn-floating-point-operations-in-to-integer-operations\/#conclusion\" >Conclusion<\/a><\/li><\/ul><\/nav><\/div>\n\n<p>&nbsp;<\/p>\n<h2><span class=\"ez-toc-section\" id=\"a-brief-note-on-notation\"><\/span>A Brief Note on Notation<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>This article is geared toward programmers, but if you happen to be a non-programmer:<\/p>\n<ul>\n<li>The &#8220;^&#8221; means, &#8220;to the power of&#8221; or exponentiation.\u00a0 So 5^2 means &#8220;5 to the power of 2&#8221;, or 5 x 5 = 25.<\/li>\n<li>You might also see &#8220;*&#8221; &#8211; in computerese, this means &#8220;multiply&#8221;.\u00a0 So 5*5 = 5 x 5 = 25.<\/li>\n<li>0x means &#8220;The following number is in hexadecimal.&#8221;\u00a0 So 0x10 is &#8220;Hex 10&#8221; or 16.\u00a0 Likewise, 0b means &#8220;the following number is in binary&#8221;.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h2><span class=\"ez-toc-section\" id=\"quick-recap-of-integers\"><\/span>Quick Recap of Integers<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Computers use binary internally to store all numbers, and all internal calculations are also performed in binary.<\/p>\n<p>For integers, this is fairly straightforward.<\/p>\n<p>Let&#8217;s recall that integers are numbers without a decimal component.\u00a0 These are all integers:<\/p>\n<ul>\n<li>0; 1; 2; etc&#8230;<\/li>\n<li>-1; -2; -3; etc&#8230;<\/li>\n<li>999,999,999;\u00a0-123,456<\/li>\n<li>123 x 10^45; -5 x 10^32<\/li>\n<\/ul>\n<p>To represent any integer number, you simply need enough bits (binary digits) such that 2^b &gt; n.<\/p>\n<p>For example, if I want to represent the integer 123,456, I need 17 bits.\u00a0 2^17 = 131,072.<\/p>\n<p>However, computers don&#8217;t just store an arbitrary number of bits &#8211; bits are always grouped by multiples of 8, and that&#8217;s how we get our basic integer data types:<\/p>\n<table>\n<tbody>\n<tr>\n<th>Bytes (Bits)<\/th>\n<th>Data Type<\/th>\n<th>Unsigned Numerical Range<\/th>\n<\/tr>\n<tr>\n<td>1 (8)<\/td>\n<td>Byte<\/td>\n<td>0 to 255<\/td>\n<\/tr>\n<tr>\n<td>2 (16)<\/td>\n<td>SmallInt<\/td>\n<td>0 to 65535<\/td>\n<\/tr>\n<tr>\n<td>4 (32)<\/td>\n<td>Int<\/td>\n<td>0 to 4.2 billion<\/td>\n<\/tr>\n<tr>\n<td>8 (64)<\/td>\n<td>LongInt \/ QuadInt<\/td>\n<td>0 to 18 quadrillion<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>This works great, until you need to represent decimal numbers, or very large numbers.<\/p>\n<p>Very large numbers are represented in exponential form, such as:<\/p>\n<ul>\n<li>1.23456 x 10^5 = 123,456<\/li>\n<li>4.2 x 10^42<\/li>\n<\/ul>\n<p>For the second example, we would need 145 bits (over 18 bytes) to represent this number!<\/p>\n<p>This, and decimals, is where floating point comes in.<\/p>\n<p>&nbsp;<\/p>\n<h2><span class=\"ez-toc-section\" id=\"what-is-a-floating-point\"><\/span>What is a Floating Point?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>A floating point is a way for computers to store and process decimal numbers.<\/p>\n<p>Floating point numbers consist of the following components:<\/p>\n<blockquote><p>s x 2^e<\/p>\n<p>s &#8211; &#8220;Significand&#8221; holds the significant digits<\/p>\n<p>2 &#8211; &#8220;Base&#8221;.\u00a0 Could be anything, but computers use base 2<\/p>\n<p>e &#8211; &#8220;Exponent&#8221;<\/p><\/blockquote>\n<p>&#8220;Floating point&#8221; means that the decimal point &#8220;floats&#8221; based on the exponent.<\/p>\n<p>Assuming that the base is always 2, we really store every floating point number as <em>two<\/em> numbers:<\/p>\n<ul>\n<li>The significand.\u00a0 In binary, every number starts with &#8220;1&#8221; except 0.\u00a0 So our significand will always be 1.bbb&#8230; unless we are truly storing the number 0.<\/li>\n<li>The exponent (in binary)<\/li>\n<\/ul>\n<p>Let&#8217;s recap:\u00a0 anything raised to a negative exponent means 1\/x.\u00a0 So:<\/p>\n<ul>\n<li>10^(-1) = 1\/10 = 0.1<\/li>\n<li>10^(-2) = 1\/100 = 0.01<\/li>\n<li>etc&#8230;<\/li>\n<\/ul>\n<p>This is important, because we need negative exponents to represent fractions.\u00a0 Without them, we could only represent integers.<\/p>\n<p>I kind of glossed over\u00a0<em>signed<\/em> integers, but our exponent can be negative, and it does this using an offset.<\/p>\n<p>In a 32-bit floating point, the exponent is 8 bits.\u00a0 If you recall, 8 bits (or one byte) can store any integer in the range of 0 to 255.\u00a0 However, the exponent is really an\u00a0<em>offset<\/em> from -127, so to get the real exponent value, you subtract 127:<\/p>\n<pre>00000000 =   0, but   0 offset from -127 = -127\r\n01111110 = 126, but 126 offset from -127 =   -1\r\n01111111 = 127, but 127 offset from -127 =    0\r\n10000000 = 128, but 128 offset from -127 =    1\r\n11111111 = 255, but 255 offset from -127 =  128<\/pre>\n<p>Because -127 and +128 have special meanings, this means that our 32-bit float can store any positive number in the range of:<\/p>\n<ul>\n<li>In base 2:\u00a0 1 x 2^(-126) to 1 x 2^127<\/li>\n<li>In base 10:\u00a0 1 x 10^(-38) to 1 x 10^38<\/li>\n<\/ul>\n<p><strong>That&#8217;s about 100 undecillion, or 100,000 trillion-trillion<\/strong><\/p>\n<p>To represent negative numbers, floating point uses a sign bit.\u00a0 If the bit is set, the entire number is negative.\u00a0 So both our number and our exponent could be negative or positive:<\/p>\n<table>\n<tbody>\n<tr>\n<td><\/td>\n<th>Exponent<br \/>\nPositive<\/th>\n<th>Exponent<br \/>\nNegative<\/th>\n<\/tr>\n<tr>\n<th>Sign<br \/>\nPositive<\/th>\n<td style=\"text-align: center;\">Positive,<br \/>\nGreater than 1<\/td>\n<td style=\"text-align: center;\">Positive,<br \/>\nFractional<\/td>\n<\/tr>\n<tr>\n<th>Sign<br \/>\nNegative<\/th>\n<td style=\"text-align: center;\">Negative,<br \/>\nLess than -1<\/td>\n<td style=\"text-align: center;\">Negative,<br \/>\nFractional<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Putting this all together, a 32-bit floating point looks like this:<\/p>\n<pre><span style=\"color: #00ff00;\">s<\/span><span style=\"color: #ffcc00;\">eeeeeeee<\/span><span style=\"color: #00ffff;\">bbbbbbbbbbbbbbbbbbbbbbb<\/span>\r\n 1 sign bit\r\n 8 exponent bits (Offset from -127)\r\n23 significand bits<\/pre>\n<p>However, recall that every number in binary, except 0, starts with a &#8220;1&#8221;.\u00a0 This includes fractions, and any other number you can think of.\u00a0 We can exploit this by always assuming that the first digit is 1, and that the significand bits encode digits 2-24, giving us 24 bits of precision, even though we only have 23 significand bits.<\/p>\n<p>To represent the number &#8220;0&#8221;, we leave both the exponent and significand empty.<\/p>\n<p>So even though we can store very large or small numbers, we only have 24 bits to store the actual digits, which equates to about 7 digits in base 10.\u00a0 This is called the precision limit.<\/p>\n<p>Here are some examples:<\/p>\n<pre>0-00000000-00000000000000000000000 = 0\r\n0-01111111-00000000000000000000000 = 1.0 x 2^(127-127) = 1.0 x 2^1 = 1\r\n0-01111110-10000000000000000000000 = 1.1 x 2^(126-127) = 0.11b = 0.75\r\n1-10000100-00100000000000000000000 = -1.001 x 2^(132-127) = -1.125 x 32 = -36<\/pre>\n<p>&nbsp;<\/p>\n<h2><span class=\"ez-toc-section\" id=\"inside-the-computer\"><\/span>Inside the Computer<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>From a program&#8217;s standpoint, there are three main components:<\/p>\n<ul>\n<li>The program itself<\/li>\n<li>Data<\/li>\n<li>CPU Registers (and other parts)<\/li>\n<\/ul>\n<p>A &#8220;register&#8221; is a temporary holding area inside the computer&#8217;s CPU.\u00a0 Like a tiny, digital, robotic arm, the program tells the register what data to grab, and what to do with it.<\/p>\n<p>It&#8217;s been over 30 years since I&#8217;ve done any assembly programming, so I&#8217;ll discuss a &#8220;generic 32-bit CPU&#8221; without getting in to specific architectures and implementations.<\/p>\n<p>Every assembly program consists of several types of instructions:<\/p>\n<table>\n<tbody>\n<tr>\n<th>Instruction<\/th>\n<th>Effect<\/th>\n<\/tr>\n<tr>\n<td>LOAD<\/td>\n<td>Go get something from memory, and put it in a register.<\/td>\n<\/tr>\n<tr>\n<td>STORE<\/td>\n<td>Take what&#8217;s in a register and put it in memory.<\/td>\n<\/tr>\n<tr>\n<td>ADD<\/td>\n<td>Add some number (or a value in memory) to the value currently in one of the registers.<\/td>\n<\/tr>\n<tr>\n<td>SUB<\/td>\n<td>Subtract some number (or a value in memory) to the value currently in one of the registers<\/td>\n<\/tr>\n<tr>\n<td>MUL<\/td>\n<td>Multiply (etc&#8230;)<\/td>\n<\/tr>\n<tr>\n<td>DIV<\/td>\n<td>Divide (etc&#8230;)<\/td>\n<\/tr>\n<tr>\n<td>SHIFTL<\/td>\n<td>Shift Left.\u00a0 Move all the bits in a specified register, some positions to the left.\u00a0 This has the effect of multiplying by 2, and since most CPUs implement SHIFT in hardware, it&#8217;s a very fast operation.<\/td>\n<\/tr>\n<tr>\n<td>SHIFTR<\/td>\n<td>Shift Right.\u00a0 Like left shift, right shift has the effect of dividing by 2.<\/td>\n<\/tr>\n<tr>\n<td>INC, DEC<\/td>\n<td>Increment or decrement &#8211; add or subtract one to the value stored in one of the registers<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>There are also instructions such as JUMP that allow for flow control, and port manipulation via IN \/ OUT, but we can ignore these in our simple example.<\/p>\n<p>Machine language is an all-numeric way to represent CPU instructions so that they can be stored as data.\u00a0 The computer reads program instruction bytes from memory, loads them in to the instruction register, and then the instruction register tells the other registers what to do based on instruction codes and other operands that are included with the instruction.<\/p>\n<p>You can think of assembly as human-readable machine language.<\/p>\n<p>When you compile something in a higher-level language like C, it takes your source code and turns it in to machine instructions, that we can then view as assembly.<\/p>\n<p>You might write this in C:<\/p>\n<pre>int i=10, j=++i, k=i+j;\r\n<span style=\"color: #008080;\">\/*   i==11, j==11, k==22  *\/<\/span><\/pre>\n<p>In assembly, it might look like this, after you compile it:<\/p>\n<pre>LOAD A $0x0A\r\nSTORE A 0xD001\r\nLOAD A 0xD001\r\nINC A\r\nSTORE A 0xD001\r\nSTORE A 0xD002\r\nLOAD A 0xD001\r\nADD A 0xD002\r\nSTORE A 0xD003<\/pre>\n<p>Of course, compilers usually have optimizers that help avoid all of the back and forth silliness, but again, this is an example.<\/p>\n<p>In the above, &#8220;A&#8221; is the CPU register &#8211; there may be as few as 2 &#8220;general purpose&#8221; registers, while most have at least 4.<\/p>\n<p>We have notation for constants, such as 0x0A, which would be interpreted as the 32-bit value, 0x0000000A (0x means &#8220;hex&#8221;).<\/p>\n<p>We also use direct notation, such as 0xD001 that specifies a memory address that the CPU&#8217;s register reads or writes.\u00a0 For simplicity, we can skip indirect notation, which acts like a pointer.<\/p>\n<p>Once we throw the code above through an optimizer, it might look like this:<\/p>\n<pre>LOAD A $0x0A\r\nSTORE A 0xD001\r\nINC A\r\nSTORE A 0xD001\r\nSTORE A 0xD002\r\nADD A 0xD002\r\nSTORE A 0xD003<\/pre>\n<p>When we load our program in to memory, the computer might look something like the table below.\u00a0 Keep in mind that the program basically shares the same memory as data, and there are pointers that point to different sections of memory for different purposes, but again, this is simplified.<\/p>\n<p>Also, remember that &#8220;LOAD A $0x0A&#8221; might be 0x0A01DD00 in machine language, but we&#8217;re viewing this in human-readable assembly&#8230;<\/p>\n<table>\n<tbody>\n<tr>\n<td style=\"width: 55px;\"><\/td>\n<th style=\"width: 130px;\">Program<\/th>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\"><\/td>\n<th style=\"width: 78px;\">Registers<\/th>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\"><\/td>\n<th style=\"width: 39px;\">Data<\/th>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\"><span style=\"color: #ffffff;\">0x0100<\/span><\/td>\n<td style=\"width: 130px;\"><span style=\"color: #ffffff;\">LOAD A $0x0A<\/span><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\">A<\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\">0xD000<\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0101<\/td>\n<td style=\"width: 130px;\">STORE A 0xD001<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\">B<\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\">0xD001<\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0102<\/td>\n<td style=\"width: 130px;\">INC A<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\">C<\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\">0xD002<\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0103<\/td>\n<td style=\"width: 130px;\">STORE A 0xD001<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\">D<\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\">0xD003<\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0104<\/td>\n<td style=\"width: 130px;\">STORE A 0xD002<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\"><\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\">0xD004<\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0105<\/td>\n<td style=\"width: 130px;\">ADD A 0xD002<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\"><\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\">&#8230;<\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0106<\/td>\n<td style=\"width: 130px;\">STORE A 0xD003<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\"><\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\"><\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0107<\/td>\n<td style=\"width: 130px;\">STOP<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\"><\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\"><\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">&#8230;<\/td>\n<td style=\"width: 130px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\"><\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\"><\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The CPU reads each instruction, which tells a specific register what to do next.<\/p>\n<p>After the first instruction, our computer looks like this:<\/p>\n<table>\n<tbody>\n<tr>\n<td style=\"width: 55px;\"><\/td>\n<th style=\"width: 130px;\">Program<\/th>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\"><\/td>\n<th style=\"width: 78px;\">Registers<\/th>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\"><\/td>\n<th style=\"width: 39px;\">Data<\/th>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0100<\/td>\n<td style=\"width: 130px;\">LOAD A $0x0A<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\">A<\/td>\n<td style=\"width: 78px;\"><span style=\"color: #00ff00;\">0x0000000A<\/span><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\">0xD000<\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\"><span style=\"color: #ffffff;\">0x0101<\/span><\/td>\n<td style=\"width: 130px;\"><span style=\"color: #ffffff;\">STORE A 0xD001<\/span><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\">B<\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\">0xD001<\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0102<\/td>\n<td style=\"width: 130px;\">INC A<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\">C<\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\">0xD002<\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0103<\/td>\n<td style=\"width: 130px;\">STORE A 0xD001<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\">D<\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\">0xD003<\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0104<\/td>\n<td style=\"width: 130px;\">STORE A 0xD002<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\"><\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\">0xD004<\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0105<\/td>\n<td style=\"width: 130px;\">ADD A 0xD002<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\"><\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\">&#8230;<\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0106<\/td>\n<td style=\"width: 130px;\">STORE A 0xD003<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\"><\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\"><\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0107<\/td>\n<td style=\"width: 130px;\">STOP<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\"><\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\"><\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">&#8230;<\/td>\n<td style=\"width: 130px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\"><\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\"><\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>As our program progresses, we move data in and out of the A register, and memory locations that represent our C variables.<\/p>\n<table>\n<tbody>\n<tr>\n<td style=\"width: 55px;\"><\/td>\n<th style=\"width: 130px;\">Program<\/th>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\"><\/td>\n<th style=\"width: 78px;\">Registers<\/th>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\"><\/td>\n<th style=\"width: 39px;\">Data<\/th>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0100<\/td>\n<td style=\"width: 130px;\">LOAD A $0x0A<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\">A<\/td>\n<td style=\"width: 78px;\"><span style=\"color: #00ff00;\">0x0000000B<\/span><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\">0xD000<\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0101<\/td>\n<td style=\"width: 130px;\">STORE A 0xD001<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\">B<\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\">0xD001<\/td>\n<td style=\"width: 39px;\"><span style=\"color: #00ff00;\">0x0000000B<\/span><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0102<\/td>\n<td style=\"width: 130px;\">INC A<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\">C<\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\">0xD002<\/td>\n<td style=\"width: 39px;\"><span style=\"color: #00ff00;\">0x0000000B<\/span><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0103<\/td>\n<td style=\"width: 130px;\">STORE A 0xD001<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\">D<\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\">0xD003<\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0104<\/td>\n<td style=\"width: 130px;\">STORE A 0xD002<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\"><\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\">0xD004<\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\"><span style=\"color: #ffffff;\">0x0105<\/span><\/td>\n<td style=\"width: 130px;\"><span style=\"color: #ffffff;\">ADD A 0xD002<\/span><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\"><\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\">&#8230;<\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0106<\/td>\n<td style=\"width: 130px;\">STORE A 0xD003<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\"><\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\"><\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0107<\/td>\n<td style=\"width: 130px;\">STOP<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\"><\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\"><\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">&#8230;<\/td>\n<td style=\"width: 130px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\"><\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\"><\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>At its final state, we add &#8220;i&#8221; and &#8220;j&#8221;, and store the result as &#8220;k&#8221;.\u00a0 Remembering that program is data and vice-versa, the last instruction, STOP, tells the CPU to stop executing instructions, so that it doesn&#8217;t start executing data!<\/p>\n<table>\n<tbody>\n<tr>\n<td style=\"width: 55px;\"><\/td>\n<th style=\"width: 130px;\">Program<\/th>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\"><\/td>\n<th style=\"width: 78px;\">Registers<\/th>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\"><\/td>\n<th style=\"width: 39px;\">Data<\/th>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0100<\/td>\n<td style=\"width: 130px;\">LOAD A $0x0A<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\">A<\/td>\n<td style=\"width: 78px;\"><span style=\"color: #00ff00;\">0x00000016<\/span><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\">0xD000<\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0101<\/td>\n<td style=\"width: 130px;\">STORE A 0xD001<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\">B<\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\">0xD001<\/td>\n<td style=\"width: 39px;\"><span style=\"color: #00ff00;\">0x0000000B<\/span><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0102<\/td>\n<td style=\"width: 130px;\">INC A<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\">C<\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\">0xD002<\/td>\n<td style=\"width: 39px;\"><span style=\"color: #00ff00;\">0x0000000B<\/span><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0103<\/td>\n<td style=\"width: 130px;\">STORE A 0xD001<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\">D<\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\">0xD003<\/td>\n<td style=\"width: 39px;\"><span style=\"color: #00ff00;\">0x00000016<\/span><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0104<\/td>\n<td style=\"width: 130px;\">STORE A 0xD002<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\"><\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\">0xD004<\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0105<\/td>\n<td style=\"width: 130px;\">ADD A 0xD002<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\"><\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\">&#8230;<\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">0x0106<\/td>\n<td style=\"width: 130px;\">STORE A 0xD003<\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\"><\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\"><\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\"><span style=\"color: #ffffff;\">0x0107<\/span><\/td>\n<td style=\"width: 130px;\"><span style=\"color: #ffffff;\">STOP<\/span><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\"><\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\"><\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 55px;\">&#8230;<\/td>\n<td style=\"width: 130px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 12px;\"><\/td>\n<td style=\"width: 78px;\"><\/td>\n<td style=\"width: 20px;\"><\/td>\n<td style=\"width: 60px;\"><\/td>\n<td style=\"width: 39px;\"><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Although this is a very simplified model, we can see what happens when we perform math operations on integers.<\/p>\n<p>&nbsp;<\/p>\n<h2><span class=\"ez-toc-section\" id=\"integer-math\"><\/span>Integer Math<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Integer math instructions look like this:<\/p>\n<ol>\n<li>Go get something<\/li>\n<li>Do something with it<\/li>\n<li>Store the result in a register<\/li>\n<\/ol>\n<p>From the CPU&#8217;s perspective, even though this is a single programming instruction, there are 3 steps, and thus it might take up to 3 CPU cycles to execute one instruction.<\/p>\n<p>Simple operations like addition are usually built right in to the register so that they only take one CPU cycle.<\/p>\n<p>Integer multiplication might take 1 or 2 extra CPU cycles, even when using purpose-specific hardware.\u00a0 Multiplication is a combination of addition and bit shifting.<\/p>\n<p>For example, to multiply 0b0101 (5) by 0b1011 (11), we would LOAD A $0x05, and then MUL A &#8220;x&#8221;, where x is some memory location.<\/p>\n<p><em><strong>Without<\/strong><\/em> a dedicated multiplier, assuming we already have 5 in the A register, here is what the CPU might do behind the scenes when we ask it to MUL A &#8220;x&#8221;:<\/p>\n<ol>\n<li>Go read memory location x (value 11)<\/li>\n<li>Multiply by A (value 5)\n<ol>\n<li>Set C to 0<\/li>\n<li>Loop from 0 to 7 (We&#8217;ll call this &#8220;S&#8221;)\n<ol>\n<li>If x AND 1\n<ol>\n<li>Store A (value 5) in B<\/li>\n<li>Shift B left by S<\/li>\n<li>Add B to C and store in C<\/li>\n<\/ol>\n<\/li>\n<li>Shift x right by 1<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<\/li>\n<li>Store C (value 55) in A<\/li>\n<\/ol>\n<p>By my count, that&#8217;s 33 CPU cycles for a single instruction!<\/p>\n<p>Modern CPUs have hardware multipliers that perform this entire process as 1 or 2 instructions, so the microcode might look like this:<\/p>\n<ol>\n<li>Go read memory location x (value 11)<\/li>\n<li>Send A to the multiplier<\/li>\n<li>Send x to the multiplier<\/li>\n<li>Read a result from the multiplier, and store in A<\/li>\n<\/ol>\n<p>Here is what an 8-bit hardware &#8220;Lattice&#8221; multiplier looks like:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-5103\" src=\"https:\/\/justinparrtech.com\/JustinParr-Tech\/wp-content\/uploads\/Floating-Points-Figures-1v2.png\" alt=\"\" width=\"573\" height=\"385\" srcset=\"https:\/\/justinparrtech.com\/JustinParr-Tech\/wp-content\/uploads\/Floating-Points-Figures-1v2.png 573w, https:\/\/justinparrtech.com\/JustinParr-Tech\/wp-content\/uploads\/Floating-Points-Figures-1v2-300x202.png 300w\" sizes=\"auto, (max-width: 573px) 100vw, 573px\" \/><\/p>\n<p>Here is how it works:<\/p>\n<ol>\n<li>As the first value is loaded, it populates the lattice, where each row is offset by one position (multiplied by 2).<\/li>\n<li>As the second value is loaded, any &#8220;zero&#8221; bits disable rows in the lattice using AND<\/li>\n<li>The remaining rows in each column of the lattice are then added to obtain two 8-bit result fields.<\/li>\n<li>The low byte and high byte are fed in to the result register, which can then be read by the CPU.<\/li>\n<\/ol>\n<p>In this example, although it takes 3 steps write to and read from the multiplier, the multiplication itself is handled instantaneously.<\/p>\n<p>&nbsp;<\/p>\n<h2><span class=\"ez-toc-section\" id=\"floating-point-math\"><\/span>Floating Point Math<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>If you recall, a floating point number is like two numbers stored as one:<\/p>\n<pre>n = s * 2^b<\/pre>\n<p>So, although you can absolutely load or store a floating point just like any other number, math isn&#8217;t so straightforward.<\/p>\n<p>Let&#8217;s assume we have two floats, n and m.\u00a0 The first step is to decode the sign, exponent, and significand:<\/p>\n<table>\n<tbody>\n<tr>\n<td><\/td>\n<th>m<\/th>\n<th>n<\/th>\n<\/tr>\n<tr>\n<td><strong>Raw number:<\/strong><\/td>\n<td><span style=\"color: #00ff00;\">174,587.904<\/span><\/td>\n<td><span style=\"color: #00ffff;\">0.30690625<\/span><\/td>\n<\/tr>\n<tr>\n<td><strong>Binary:<\/strong><\/td>\n<td><span style=\"color: #00ff00;\">101010100111111011.11100111011<\/span><\/td>\n<td><span style=\"color: #00ffff;\">0.01001110100<\/span><\/td>\n<\/tr>\n<tr>\n<td><strong>Significand<br \/>\nand Exponent:<\/strong><\/td>\n<td><span style=\"color: #00ff00;\">s = 1.01010100111111011111001<\/span><br \/>\n<span style=\"color: #00ff00;\">e = 10001<\/span><\/td>\n<td><span style=\"color: #00ffff;\">s = 1.001110100<\/span><br \/>\n<span style=\"color: #00ffff;\">e = -10<\/span><\/td>\n<\/tr>\n<tr>\n<td><strong>Encoded:<\/strong><\/td>\n<td><span style=\"color: #00ff00;\">0-10010000-<\/span><br \/>\n<span style=\"color: #00ff00;\">01010100111111011111001<\/span><\/td>\n<td><span style=\"color: #00ffff;\">0-10000001-<\/span><br \/>\n<span style=\"color: #00ffff;\">00111010000000000000000<\/span><\/td>\n<\/tr>\n<tr>\n<td><strong>Base 10:<\/strong><\/td>\n<td><span style=\"color: #00ff00;\">1.3319998979568 x 2^17<\/span><\/td>\n<td><span style=\"color: #00ffff;\">1.227625 x 2^(-2)<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Remember the special case of zero:<\/p>\n<p>If e=0 (after shift) and s=0 then the value is 0.\u00a0 For our example, this is not the case, but the CPU still has to deal with checking for a zero and other special values, which takes time.<\/p>\n<p>Floating point multiplication is actually easier than addition:<\/p>\n<table>\n<tbody>\n<tr>\n<th>Step<\/th>\n<th>Result<\/th>\n<\/tr>\n<tr>\n<td>1. Multiply ms * ns<\/td>\n<td><span style=\"color: #00ff00;\">1.3319998979568<\/span> x <span style=\"color: #00ffff;\">1.227625<\/span>\u00a0=<br \/>\n<span style=\"color: #ffff00;\">1.6351963747292166<\/span><\/td>\n<\/tr>\n<tr>\n<td>2. While result &gt; 2,<br \/>\ndivide by 2, add 1 to me<\/td>\n<td>(n\/a)<\/td>\n<\/tr>\n<tr>\n<td>3. Add me + ne<\/td>\n<td><span style=\"color: #00ff00;\">17<\/span> + (<span style=\"color: #00ffff;\">-2<\/span>) =<br \/>\n<span style=\"color: #ffff00;\">15<\/span><\/td>\n<\/tr>\n<tr>\n<td>4. Re-encode the result<\/td>\n<td>s = <span style=\"color: #ffff00;\">1.6351963747292166<\/span><br \/>\ne = <span style=\"color: #ffff00;\">15<\/span><\/td>\n<\/tr>\n<tr>\n<td>(In decimal)<\/td>\n<td><span style=\"color: #ffff00;\">53,582.11328125<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>This seems complicated, but addition is even more so:<\/p>\n<table>\n<tbody>\n<tr>\n<th>Step<\/th>\n<th>Result<\/th>\n<\/tr>\n<tr>\n<td>1. If n&gt;m then swap n,m<br \/>\n(Ensure n&lt;m)<br \/>\n1.a. Compare exponents<br \/>\n1.b. If exponents are equal,<br \/>\ncompare significands<\/td>\n<td>No swap required<\/td>\n<\/tr>\n<tr>\n<td>2. Subtract ne-me = ee<\/td>\n<td><span style=\"color: #00ffff;\">-2<\/span> &#8211; <span style=\"color: #00ff00;\">17<\/span> = <span style=\"color: #ffff00;\">-19<\/span><\/td>\n<\/tr>\n<tr>\n<td>3. Left shift ns by ee<br \/>\n(Note that a negative left<br \/>\nshift is a right shift)<\/td>\n<td><span style=\"color: #00ffff;\">1.227625<\/span> &lt;&lt; <span style=\"color: #ffff00;\">-19<\/span> =<br \/>\n<span style=\"color: #00ffff;\">0.00000234150886536<\/span><\/td>\n<\/tr>\n<tr>\n<td>4. Add ns to ms = ss<\/td>\n<td><span style=\"color: #00ff00;\">1.3319998979568<\/span> + <span style=\"color: #00ffff;\">0.00000234150886536<\/span>\u00a0=<br \/>\n<span style=\"color: #ffff00;\">1.33200223946<\/span><\/td>\n<\/tr>\n<tr>\n<td>5. While result &gt;2,<br \/>\ndivide by 2, add 1 to me<\/td>\n<td>n\/a<\/td>\n<\/tr>\n<tr>\n<td>6. Re-encode the result<\/td>\n<td>s = <span style=\"color: #ffff00;\">1.33200223946<\/span><span style=\"color: #ffff00;\"><br \/>\n<\/span>e = <span style=\"color: #ffff00;\">17<\/span><\/td>\n<\/tr>\n<tr>\n<td>(In decimal)<\/td>\n<td><span style=\"color: #ffff00;\">174,588.19753<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Just as integer multiplication would chew up CPU cycles without special hardware, most modern CPUs have floating point hardware (called a Floating Point Unit) that is dedicated to floating point math and manipulation.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h2><span class=\"ez-toc-section\" id=\"comparing-floats-to-ints\"><\/span>Comparing Floats to Ints<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The point of demonstrating all of this complexity is to show all of the extra work that has to be done to support floating point numbers, compared to integers.<\/p>\n<p>We&#8217;ve looked at the internal CPU process, and it&#8217;s easy to see why floats are slower than ints:<\/p>\n<table>\n<tbody>\n<tr>\n<th>Floating Point<\/th>\n<th>Integer<\/th>\n<\/tr>\n<tr>\n<td>Special cases include zero, infinity, and infinitesimal, that all require extra handling steps.<\/td>\n<td>Integers have no special cases.<\/td>\n<\/tr>\n<tr>\n<td>Each floating point consists of two numbers, each pair requiring separate manipulation and normalization steps.<\/td>\n<td>All integers are a single component.<\/td>\n<\/tr>\n<tr>\n<td>Floating point arithmetic, even if implemented in hardware, requires a discreet set of steps that can be computationally-expensive.<\/td>\n<td>Integer arithmetic, if implemented in hardware, only requires 1 or 2 steps.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>What all of this means is that the CPU has to work harder during floating-point operations compared to integer operations:<\/p>\n<ul>\n<li>On older CPUs that don&#8217;t have dedicated FPU support, floating point arithmetic can take up to 4 times longer.<\/li>\n<li>On newer CPUs with dedicated FPU hardware, parallel pipelines, and conditional execution, floating point arithmetic can be as little as 1.3 times longer.<\/li>\n<\/ul>\n<p>One more complication:\u00a0 If you perform a math operation on a float and an int, the CPU must convert it to float, which adds an extra step:<\/p>\n<table>\n<tbody>\n<tr>\n<td><\/td>\n<th>Integer<\/th>\n<th>Floating Point<\/th>\n<\/tr>\n<tr>\n<th>Integer<\/th>\n<td><span style=\"color: #00ff00;\">Integer Operation<\/span><\/td>\n<td><span style=\"color: #ffff00;\">Convert Int to Float<\/span><br \/>\nFloating Point Operation<\/td>\n<\/tr>\n<tr>\n<th>Floating Point<\/th>\n<td><span style=\"color: #ffff00;\">Convert Int to Float<\/span><br \/>\nFloating Point Operation<\/td>\n<td>Floating Point Operation<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Although it may seem trivial, converting an int to floating point entails these steps:<\/p>\n<ol>\n<li>Set e=0<\/li>\n<li>Preserve the sign bit = b<\/li>\n<li>if n&lt;0 then convert n to +n<\/li>\n<li>Loop\n<ol>\n<li>if s and 0x80000000 = 1 exit loop (we found the high bit)<\/li>\n<li>left shift s by 1<\/li>\n<li>increment e<\/li>\n<li>if e&gt;31 exit loop (all zeros)<\/li>\n<\/ol>\n<\/li>\n<li>Convert b,e,s to float\n<ol>\n<li>Send b to FPU<\/li>\n<li>Send e to FPU<\/li>\n<li>Send s to FPU<\/li>\n<li>Read result from FPU to register A<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<p>The last step assumes that the actual conversion is done in hardware, but here is what would happen inside that hardware:<\/p>\n<ul>\n<li>When the b register is loaded, shift left by 31<\/li>\n<li>When the s register is loaded&#8230;\u00a0 shift right 8\u00a0 (only 24 bits of precision)<\/li>\n<li>When the e register is loaded, add 127\u00a0 (e will never be negative because we know n was an integer)<\/li>\n<li>left shift e by 30<\/li>\n<li>combine b OR e OR s<\/li>\n<\/ul>\n<p>So the simple act of converting an int to a float is fairly computationally-expensive.<\/p>\n<p>This gives us a hint about how to optimize our code&#8230;<\/p>\n<ol>\n<li>Reduce Integer to Floating Point conversions<\/li>\n<li>Reduce Floating Point Operations (FLOps)<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h2><span class=\"ez-toc-section\" id=\"how-to-convert-operations-to-integer-only-pt-1-%e2%80%93-beginner-mode\"><\/span>How to Convert Operations to Integer-Only, Pt 1 &#8211; Beginner Mode<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Here is a simple example:<\/p>\n<p>Let&#8217;s say that you have a function that returns an integer value in the range of 0 to 1023, but you want to scale it by 2\/3.<\/p>\n<p>If you really suck at coding, your code might look like this:<\/p>\n<pre>int i;\r\nfloat k;\r\ni=somefunction();\r\nk=i*0.66;\r\ni=cint(k);<\/pre>\n<p>Here is what the code above does&#8230;<\/p>\n<ol>\n<li>Declare variables<\/li>\n<li>Capture our integer function output in &#8216;i&#8217;<\/li>\n<li>Multiply by 0.66, which as we expect, results in a float.\u00a0 We capture the float output in &#8216;k&#8217;<\/li>\n<li>Finally, we convert our scaled float back to int with cint, storing the result back in &#8216;i&#8217;<\/li>\n<\/ol>\n<p>Let&#8217;s see why this code is horrible&#8230; Here is what the CPU has to do:<\/p>\n<ol>\n<li>JUMP to somefunction<\/li>\n<li>POP A from the stack (result); cost = 1<\/li>\n<li>Store A as &#8216;i&#8217; (assign our function result to &#8216;i&#8217;); cost = 1<\/li>\n<li>Convert A to floating point (preparing for floating point operation); cost = 5<\/li>\n<li>Multiply by 0.66; cost = 6<\/li>\n<li>Store the result as &#8216;k&#8217;; cost = 1<\/li>\n<li>Convert A to integer from float; cost = 6<\/li>\n<li>Store the result as &#8216;i&#8217;; cost = 1<\/li>\n<\/ol>\n<p>Total cost: 21<\/p>\n<p>We quickly realize that if you assign a float to an integer variable, the conversion is done automatically.\u00a0 Even better, we don&#8217;t need an intermediate assignment, as we can handle the scaling inline:<\/p>\n<pre>int i;\r\ni=somefunction()*0.66;<\/pre>\n<p>Better, but NOT MUCH BETTER.\u00a0 Here is what your CPU sees:<\/p>\n<ol>\n<li>JUMP to somefunction<\/li>\n<li>POP A from the stack (result); cost = 1<\/li>\n<li>Convert A to float; cost = 5<\/li>\n<li>Multiply A * $0.66; cost = 6<\/li>\n<li>Convert A to int; cost = 6<\/li>\n<li>Store the result as &#8216;i&#8217;; cost = 1<\/li>\n<\/ol>\n<p>Total cost = 19<\/p>\n<p>So although your code looks more efficient, IT&#8217;S NOT.<\/p>\n<p>How about this:<\/p>\n<pre>int i;\r\ni=somefunction()*2\/3;<\/pre>\n<p>At first, this looks exactly like what we had above, but let&#8217;s look at how the CPU sees this:<\/p>\n<ol>\n<li>JUMP to somefunction<\/li>\n<li>POP A from the stack (result); cost = 1<\/li>\n<li>MUL A $2; cost = 4<\/li>\n<li>DIV A $3; cost = 4<\/li>\n<li>Store &#8216;i&#8217;; cost = 1<\/li>\n<\/ol>\n<p>Total cost: 10<\/p>\n<p><strong>Wait&#8230;. what???<\/strong><\/p>\n<ul>\n<li>Since we didn&#8217;t use any floating point values, there were no floating point conversions<\/li>\n<li>Since we didn&#8217;t use any floating point variables, the compiler automatically decided that no intermediate conversions were necessary<\/li>\n<li>We still have 5 instead of 6 steps, BUT&#8230; we have two FASTER integer operations instead of one SLOW FLOp, and no conversions.<\/li>\n<\/ul>\n<p>So, even though we have almost as many steps, this code requires only about 50% of the CPU cycles, and is up to twice as fast!<\/p>\n<p>Here is the interesting part&#8230;<\/p>\n<p>If you integer-divide 2\/3, the result is 0.\u00a0 If we multiply 1023 by (2\/3) the integer answer will always be 0.<\/p>\n<p>But&#8230; 1023 * 2 = 2046 \/ 3 = 682<\/p>\n<p><strong>So, if we change the order of operations &#8211; multiply first, divide next, then we get the desired result without having to use floating points.<\/strong><\/p>\n<p>&nbsp;<\/p>\n<h2><span class=\"ez-toc-section\" id=\"how-to-convert-operations-to-integer-only-pt-2-%e2%80%93-expert-mode\"><\/span>How to Convert Operations to Integer-Only, Pt 2 &#8211; Expert Mode<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Let&#8217;s say that we want to map the output of our same function (0..1023) to an angle in radians.<\/p>\n<p>Just to recap, in degrees, a circle is 360 degrees.\u00a0 It&#8217;s sliced up in to 360 neat little slices, and 360 degrees is at the same position as zero.\u00a0 In radians, the circle is divided in to 2\u03c0 slices.\u00a0 So 0 and 2\u03c0 sit at the same location, 90 degrees is \u03c0\/2 (about 1.57) radians, 180 degrees is \u03c0 (about 3.14) radians, and 270 degrees is at 3\u03c0\/2 radians (about 4.71).<\/p>\n<p>In computing, we typically use radians over degrees for two reasons:<\/p>\n<ol>\n<li>There are some math shortcuts where things cancel out, when you consider the unit circle in radians instead of degrees.<\/li>\n<li>Most compilers and math libraries implement trig functions in radians, not degrees.<\/li>\n<\/ol>\n<p>So if we want to convert our function output (0..1023) to an angle in radians (0..2\u03c0), the calculation looks like this:<\/p>\n<pre>int i;\r\nfloat k;\r\n\r\n<span style=\"color: #008080;\">\/* Get our function output *\/<\/span>\r\ni=somefunction();\r\n\r\n<span style=\"color: #008080;\">\/* Convert i to an interval of 0..1 *\/<\/span>\r\nk=i\/1023;\r\n\r\n<span style=\"color: #008080;\">\/* Multiply by the length around the unit circle *\/<\/span>\r\nk=k*2*PI();<\/pre>\n<ul>\n<li>Int Ops: 1 * 4<\/li>\n<li>Conversions: 1 * 5<\/li>\n<li>FLOPs: 3 * 6<\/li>\n<li><em>Total Cost:\u00a0 27<\/em><\/li>\n<\/ul>\n<p>Note:\u00a0 In the given context, the compiler will store 1023 and 2 as floats, so no conversion is necessary.<\/p>\n<p>Simplified:<\/p>\n<pre><span style=\"color: #008080;\">\/* int i; *\/<\/span>\r\nfloat k;\r\n\r\nk=somefunction()\/1023*2*PI();<\/pre>\n<ul>\n<li>Int Ops: 0 * 4<\/li>\n<li>Conversions: 1 * 5\u00a0 (output from somefunction)<\/li>\n<li>FLOps: 3 * 6<\/li>\n<li><em>Total Cost: 23<\/em><\/li>\n<\/ul>\n<p>At first, this looks optimum because the result is a float, and there is no way around this.<\/p>\n<p>However, we can rearrange things so that there are fewer FLOps:<\/p>\n<pre>int i;\r\nfloat k;\r\n\r\ni=function()*2\/1023;\r\nk=i*PI();<\/pre>\n<ul>\n<li>Int Ops: 2 * 4<\/li>\n<li>Conversions: 1 * 5<\/li>\n<li>FLOps: 1 * 6<\/li>\n<li><em>Total Cost:\u00a0 19<\/em><\/li>\n<\/ul>\n<p>Now, everything is an integer until the last step, and the cost savings is evident.<\/p>\n<p>BUT&#8230;<\/p>\n<p>There is a problem.<\/p>\n<p>Remember that our function ranges from 0..1023.\u00a0 We multiply first, then divide.\u00a0 However, by immediately storing an integer result, we lose any decimal granularity.\u00a0 We effectively have a function that returns 0 or 1, which we then multiply by PI in the last step.\u00a0 Let&#8217;s look at a range of values, and see how this plays out.<\/p>\n<pre>f() =    0 * 2 = 0    \/ 1023 = 0 * PI = 0\r\nf() =  128 * 2 = 256  \/ 1023 = 0 * PI = 0\r\nf() =  256 * 2 = 512  \/ 1023 = 0 * PI = 0\r\nf() =  384 * 2 = 768  \/ 1023 = 0 * PI = 0\r\nf() =  512 * 2 = 1024 \/ 1023 = 1 * PI = 3.14159\r\nf() =  640 * 2 = 1280 \/ 1023 = 1 * PI = 3.14159\r\nf() =  768 * 2 = 1536 \/ 1023 = 1 * PI = 3.14159\r\nf() =  896 * 2 = 1792 \/ 1023 = 1 * PI = 3.14159\r\nf() = 1023 * 2 = 2046 \/ 1023 = 1 * PI = 3.14159<\/pre>\n<p>We effectively lose all precision after the decimal, which we need in order to avoid this &#8220;stepping&#8221; problem.<\/p>\n<p>We can use some basic algebra to fix the stepping problem by retaining some precision, without losing our efficient integer operations.<\/p>\n<ul>\n<li>If we pre-calculate PI to a specific precision, we can deal with it as a fraction of integers:<br \/>\n3.14159 = 314159\/100000<\/li>\n<li>We can pre-calculate other constants:<br \/>\n2 * 314159 \/ 1023 = 614 (and some fraction that we will ignore, assuming we have suitable precision)<\/li>\n<\/ul>\n<pre><span style=\"color: #008080;\">\/* 2 * 314159 \/ 1023 *\/<\/span>\r\nconst C=614;\r\n\r\n<span style=\"color: #008080;\">\/* Return k to a decimal.  Note the \r\n   use of .0 to force D to be a  \r\n   floating point.  *\/<\/span>\r\nconst D=100000.0;   \r\n\r\nint i;\r\nfloat k; \r\n\r\ni=function()*C; \r\n\r\nk=i\/D;<\/pre>\n<ul>\n<li>Int Ops: 1 * 4<\/li>\n<li>Conversions: 1 * 5<\/li>\n<li>FLOps: 1 * 6<\/li>\n<li><em>Total Cost:\u00a0 15<\/em><\/li>\n<\/ul>\n<p>This approach is even cheaper, and a quick check of the output will determine that we&#8217;ve fixed the &#8220;stepping&#8221; problem:<\/p>\n<pre>f() =    0 * 614 =      0 \/ 100000.0 = 0.00000 \r\nf() =  128 * 614 =  78592 \/ 100000.0 = 0.78592\r\nf() =  256 * 614 = 157184 \/ 100000.0 = 1.57184 \r\nf() =  384 * 614 = 235776 \/ 100000.0 = 2.35776\r\nf() =  512 * 614 = 314368 \/ 100000.0 = 3.14368\r\nf() =  640 * 614 = 392960 \/ 100000.0 = 3.92960\r\nf() =  768 * 614 = 471552 \/ 100000.0 = 4.71552\r\nf() =  896 * 614 = 550144 \/ 100000.0 = 5.50144\r\nf() = 1023 * 614 = 628122 \/ 100000.0 = 6.28122<\/pre>\n<p>MUCH better!<\/p>\n<p>&nbsp;<\/p>\n<h2><span class=\"ez-toc-section\" id=\"how-to-convert-operations-to-integer-only-pt-3-%e2%80%93-super-advanced-mode\"><\/span>How to Convert Operations to Integer-Only, Pt 3 &#8211; Super Advanced Mode<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><strong>Lookup tables.<\/strong><\/p>\n<p>Hang on&#8230; you&#8217;re in for a ride, but we&#8217;ll get there together.<\/p>\n<p>Let&#8217;s say you want to draw a circle &#8211; we&#8217;ll use an imaginary function called &#8220;plot(x,y)&#8221; to draw one pixel:<\/p>\n<pre><span style=\"color: #008080;\">\/* Set radius              *\/<\/span>\r\nint r=100;\r\n\r\n<span style=\"color: #008080;\">\/* Calculate circumference *\/<\/span>\r\nint c=r*2*PI();\r\n\r\n<span style=\"color: #008080;\">\/* Circle center coords    *\/<\/span>\r\nint cx=200,cy=200;\r\n\r\n<span style=\"color: #008080;\">\/* One of the advantages of using radians\r\n   is that the incremental angle = 1\/r    *\/<\/span>\r\nfloat a=0,ai=1\/r;\r\n\r\nint x,y,i;\r\nfor (i=0; i&lt;c; i++) {\r\n    a=i*ai;         <span style=\"color: #008080;\">\/* Angle        *\/<\/span>\r\n    x=cos(a)*r+cx;  <span style=\"color: #008080;\">\/* X coord      *\/<\/span>\r\n    y=sin(a)*r+cy;  <span style=\"color: #008080;\">\/* Y coord      *\/<\/span>\r\n    plot(x,y);      <span style=\"color: #008080;\">\/* Draw 1 pixel *\/<\/span>\r\n}<\/pre>\n<p>This plots a 200-pixel diameter circle whose center is (200,200).<\/p>\n<p>The trick used to calculate the incremental angle &#8211; the angle we need for just one pixel at the circumference, works like this:<\/p>\n<ul>\n<li>Circumference of circle: c=2*r*\u03c0, which is also the exact number of pixels we need to draw.<\/li>\n<li>If r=1, then the circumference of a unit circle is simply 2\u03c0, which is also the number of radians around the circumference.<\/li>\n<li>So if we take any circle, the number of radians per pixel (the angle by which we have to shift to draw the next adjacent pixel) is 2\u03c0\/c<\/li>\n<li>If we substitute c:\u00a0 2\u03c0\/2r\u03c0<\/li>\n<li>Everything cancels:\u00a0 ai=1\/r<\/li>\n<li>Example:\u00a0 We have a circle of radius 1, 1\/1=1.\u00a0 Since the circumference is about 6, the incremental angle being 1 means we will draw 2\u03c0\/1 = about 6 pixels.<\/li>\n<li>Example, radius 100:\u00a0 c=628;\u00a0 ai=1\/100 = 0.01<\/li>\n<\/ul>\n<p>Because we go through the circle only once, there is no real advantage to pre-calculating a lookup table, nor even in using all-integer calculations.<\/p>\n<p>We can even draw a disc with no wasted cycles, even using floats:<\/p>\n<pre><span style=\"color: #008080;\">\/* Radius            *\/<\/span>\r\nint r=100;\r\n\r\n<span style=\"color: #008080;\">\/* 1\/2 Circumference *\/<\/span>\r\nint c=r*PI();\r\n\r\n<span style=\"color: #008080;\">\/* Circle Center     *\/<\/span>\r\nint cx=200,cy=200;\r\n\r\n<span style=\"color: #008080;\">\/* Incremental Angle *\/<\/span>\r\nfloat a,ai=1\/r;\r\n\r\nint x,y,y1,y2,i;\r\n\r\n<span style=\"color: #008080;\">\/* To draw a disc, we only need quadrants 1 and 2.<\/span>\r\n<span style=\"color: #008080;\">   We will use cy-y and cy+y for each vertical line, \r\n   then <\/span><span style=\"color: #008080;\">draw a line between the two.  This draws the<\/span>\r\n<span style=\"color: #008080;\">   disc from right to left.                        <\/span>\r\n<span style=\"color: #008080;\">   It's a bit confusing, but y is NEGATIVE in Q1<\/span>\r\n<span style=\"color: #008080;\">   and Q2, so sin(a) will return a negative, and we <\/span>\r\n<span style=\"color: #008080;\">   ADD to cy to subtract (y1) and then subtract<\/span>\r\n<span style=\"color: #008080;\">   in order to add to obtain y2.                     *\/<\/span>\r\nfor(i=0; i&lt;c; i++){\r\n    a =i*ai;           <span style=\"color: #008080;\">\/* Calculate angle                *\/<\/span>\r\n    x =cx+cos(a)*r;    <span style=\"color: #008080;\">\/* X coord                        *\/<\/span>\r\n    y =sin(a)*r;       <span style=\"color: #008080;\">\/* Y offset - should be negative  *\/<\/span>\r\n    y1=cy+y;           <span style=\"color: #008080;\">\/* Start y                        *\/<\/span>\r\n    y2=cy-y;           <span style=\"color: #008080;\">\/* End y                          *\/<\/span>\r\n    for (y=y1; y&lt;=y2; y++) {\r\n        plot(x,y);\r\n    }\r\n}<\/pre>\n<p>This draws a 200-pixel-wide disc centered at (200,200).<\/p>\n<p><strong>What if we want to draw a sphere?<\/strong><\/p>\n<ul>\n<li>We can use the same trick we used with the disc &#8211; calculate +y and -y and draw a line between the two<\/li>\n<li>Due to z-clipping, we only see one pixel.\u00a0 Rather than waste cycles drawing what we can&#8217;t see, we simply calculate the closest z value for each (x,y) on the shell of the sphere, and everything farther away at that (x,y) is clipped.<\/li>\n<li>We need sin, cos for calculating (x,y), but then for a given (x,y), we need cos again to calculate z.\u00a0 Think of each (x,-y..y) as the cross-section of a half-disc.\u00a0 At -y or +y, z is zero, but as y approaches 0, z approaches x.<\/li>\n<li>Since we will calculate <strong>cos(x) iteratively \u03c0r^2<\/strong> times, this is a good place to build a lookup table!<\/li>\n<li>We get less benefit from sin(y) since we only need it once, but pre-calculating will keep things consistent.<\/li>\n<\/ul>\n<pre><span style=\"color: #008080;\">\/* Precision *\/<\/span>\r\nconst PRECISION=10000;\r\n\r\n<span style=\"color: #008080;\">\/* Radius *\/<\/span>\r\nint r=100;\r\n\r\n<span style=\"color: #008080;\">\/* 1\/2 Circumference at z=0 *\/<\/span>\r\nint c=r*PI();\r\n\r\n<span style=\"color: #008080;\">\/* Center *\/<\/span>\r\nint cx=200;cy=200;cz=0;\r\n\r\n<span style=\"color: #008080;\">\/* Incremental Angle *\/<\/span>\r\nfloat a,ai=1\/r;\r\n\r\n<span style=\"color: #008080;\">\/* Utility variables *\/<\/span>\r\nint x,y,y1,y2,y3,z,i;\r\n\r\n<span style=\"color: #008080;\">\/* LOOKUP TABLES!! *\/<\/span>\r\nint lcos[c], lsin[c];\r\n\r\nfor (i=0;i&lt;c;i++) {\r\n    a=ai*i;\r\n    lcos[i]=cos(a)*PRECISION;\r\n    lsin[i]=sin(a)*PRECISION;\r\n}\r\n<span style=\"color: #008080;\">\/* That was the last FLOp *\/<\/span>\r\n\r\n<span style=\"color: #008080;\">\/* Draw sphere surface *\/<\/span>\r\nfor (i=0;i&lt;c;i++){\r\n    x =lcos[i]*r\/PRECISION+cx;\r\n    y1=lsin[i]*r\/PRECISION;            <span style=\"color: #008080;\">\/* Negative in Q1,Q2             *\/<\/span>\r\n    y2=-y1;                            <span style=\"color: #008080;\">\/* Reflect across 0 to get Q4,Q3 *\/<\/span>\r\n    y3=y2+y2;                          <span style=\"color: #008080;\">\/* Pre-compute the height of the<\/span>\r\n<span style=\"color: #008080;\">                                          current slice                 *\/<\/span>\r\n    for (y=y1; y&lt;=y2; y++) {\r\n        z=(y+y2)*100\/y3;               <span style=\"color: #008080;\">\/* Use 0..2*y2 to generate a<\/span>\r\n<span style=\"color: #008080;\">                                          lookup value 0..100           *\/<\/span>\r\n        z=lcos[z]*y2\/PRECISION+cz;     <span style=\"color: #008080;\">\/* Generate z using lookup and \r\n                                          half the slice radius, y2     *\/<\/span>\r\n        plot(x,y+cy,z);                <span style=\"color: #008080;\">\/* Plot - note y+cy in order to \r\n                                          apply the y offset            *\/<\/span>\r\n    }\r\n}<\/pre>\n<p>In addition to accomplishing this with all integers, we also eliminate the function calls.<\/p>\n<p>Function calls are also one of those quasi-expensive CPU operations, which involves pushing parameters on to a stack, setting up a private variable space, and then a far jump to some code &#8220;in the memory cloud&#8221; somewhere.\u00a0 On return, the return value is pushed on to the stack, and another far jump back to the next instruction.<\/p>\n<p>This method can be used for trig functions, 3D transformations, and even logarithms.<\/p>\n<p>For example, if you pre-compute log and inverse-log tables (llog[] and lilog[]) you can do things like compute the square root, all in integer space:<\/p>\n<pre>lilog[llog[25]\/llog[2]]==5<\/pre>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h2><span class=\"ez-toc-section\" id=\"conclusion\"><\/span>Conclusion<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Faster is better.<\/p>\n<p>Int Ops are always faster than FLOps.<\/p>\n<p>This is why FLOp Per Second (FLOPS) is a common measure of computing power, over &#8220;(Integer) Instructions Per Second&#8221;.<\/p>\n<p>The better your CPU, the more efficiently you can process a FLOp, and therefore, the more FLOps you can compute in one second.<\/p>\n<p>However, your code will always be faster with fewer FLOps, regardless of how powerful your CPU, or how efficiently it handles floating point conversion and arithmetic.<\/p>\n<ul>\n<li>Multiply before Divide<\/li>\n<li>Refactor, if you have a stepping problem<\/li>\n<li>Use lookup tables for repetitive floating point operations (or function calls)<\/li>\n<\/ul>\n<p>Have fun!<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Or, why floating point operations are slow, and how to avoid them.<\/p>\n","protected":false},"author":16,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[17,20],"tags":[],"class_list":["post-5060","post","type-post","status-publish","format-standard","hentry","category-good-design-bad-design","category-science"],"_links":{"self":[{"href":"https:\/\/justinparrtech.com\/JustinParr-Tech\/wp-json\/wp\/v2\/posts\/5060","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/justinparrtech.com\/JustinParr-Tech\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/justinparrtech.com\/JustinParr-Tech\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/justinparrtech.com\/JustinParr-Tech\/wp-json\/wp\/v2\/users\/16"}],"replies":[{"embeddable":true,"href":"https:\/\/justinparrtech.com\/JustinParr-Tech\/wp-json\/wp\/v2\/comments?post=5060"}],"version-history":[{"count":10,"href":"https:\/\/justinparrtech.com\/JustinParr-Tech\/wp-json\/wp\/v2\/posts\/5060\/revisions"}],"predecessor-version":[{"id":5152,"href":"https:\/\/justinparrtech.com\/JustinParr-Tech\/wp-json\/wp\/v2\/posts\/5060\/revisions\/5152"}],"wp:attachment":[{"href":"https:\/\/justinparrtech.com\/JustinParr-Tech\/wp-json\/wp\/v2\/media?parent=5060"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/justinparrtech.com\/JustinParr-Tech\/wp-json\/wp\/v2\/categories?post=5060"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/justinparrtech.com\/JustinParr-Tech\/wp-json\/wp\/v2\/tags?post=5060"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}