<p>On an 8-bit micro controller I would like to do the following:</p>

<pre><code>16bit_integer = another_16bit_integer * 0.997;</code></pre>

<p>with the least possible number of instructions.</p>

[{'answer_id': 27415, 'author': 'T Percival', 'author_id': 954, 'author_profile': 'https://Stackoverflow.com/users/954', 'pm_score': 2, 'selected': False, 'text': '<p>How about integer arithmetic in 32 bits?</p>\n\n<pre><code>16bit_integer = (int16_t) (another_16bit_integer * (int32_t) 997 / 1000);\n</code></pre>\n\n<p>32 bits will be enough to store (INT16_MAX × 997), do the sum on values 1000 times larger then divide back to your 16 bit scale.</p>\n'}, {'answer_id': 27418, 'author': 'Justin Tanner', 'author_id': 609, 'author_profile': 'https://Stackoverflow.com/users/609', 'pm_score': 1, 'selected': False, 'text': '<p>On my platform ( Atmel AVR 8-bit micro-controller, running gcc )</p>\n\n<pre><code>16bit_integer = another_16bit_integer * 0.997;</code></pre>\n\n<p>Takes about 26 instructions.</p>\n\n<pre><code>16bit_integer = (int16_t) (another_16bit_integer * (int32_t) 997 / 1000);</code></pre>\n\n<p>Takes about 25 instructions.</p>\n'}, {'answer_id': 27451, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 0, 'selected': False, 'text': '<p>Precomputed lookup table:</p>\n\n<pre><code>16bit_integer = products[another_16bit_integer];\n</code></pre>\n'}, {'answer_id': 27479, 'author': 'Josh', 'author_id': 257, 'author_profile': 'https://Stackoverflow.com/users/257', 'pm_score': 0, 'selected': False, 'text': "<blockquote>\n  <p>Precomputed lookup table:</p>\n</blockquote>\n\n<pre><code>16bit_integer = products[another_16bit_integer];\n</code></pre>\n\n<p>That's not going to work so good on the AVR, the 16bit address space is going to be exhausted.</p>\n"}, {'answer_id': 27481, 'author': 'Mike Thompson', 'author_id': 2754, 'author_profile': 'https://Stackoverflow.com/users/2754', 'pm_score': 0, 'selected': False, 'text': '<p>Since you are using an 8 bit processor, you can probably only handle 16 bit results, not 32 bit results. To reduce 16 bit overflow issues I would restate the formula like this:</p>\n\n<pre><code>result16 = operand16 - (operand16 * 3)/1000\n</code></pre>\n\n<p>This would give accurate results for unsigned integers up to 21845, or signed integers up to 10922. I am assuming the the processor can do 16 bit integer division. If you cannot then you need to do the division the hard way. Multiplying by 3 can be done by simple shifts &amp; adds, if no multiply instruction exists or if multiplication only works with 8 bit operands.</p>\n\n<p>Without knowing the exact microprocessor it is impossible to determine how long such a calculation would take.</p>\n'}, {'answer_id': 27483, 'author': 'Josh', 'author_id': 257, 'author_profile': 'https://Stackoverflow.com/users/257', 'pm_score': 0, 'selected': False, 'text': '<blockquote>\n  <p>On my platform ( Atmel AVR 8-bit micro-controller, running gcc )</p>\n</blockquote>\n\n<pre><code>16bit_integer = another_16bit_integer * 0.997;\n</code></pre>\n\n<blockquote>\n  <p>Takes about 26 instructions.</p>\n</blockquote>\n\n<pre><code>16bit_integer = (int16_t) (another_16bit_integer * (int32_t) 997 / 1000);\n</code></pre>\n\n<blockquote>\n  <p>Takes about 25 instructions.</p>\n</blockquote>\n\n<p>The <a href="http://en.wikipedia.org/wiki/Atmel_AVR" rel="nofollow noreferrer">Atmel AVR</a> is a RISC chip, so counting instructions is a valid comparison.</p>\n'}, {'answer_id': 28013, 'author': 'Mike Haboustak', 'author_id': 2146, 'author_profile': 'https://Stackoverflow.com/users/2146', 'pm_score': 2, 'selected': False, 'text': '<p>You probably meant to have some rounding in there, rather than truncating the result to an integer, otherwise the purpose of the operation is really limited. </p>\n\n<p>But since you asked the question with that specific formula, it brought to mind that your result set is really coarse. For the first 333 numbers, the result is: another_16bit_integer-1. You can approximate it (maybe even exactly, when not performed in my head) with something like:</p>\n\n<pre><code>16bit_integer = another_16bit_integer - 1 - (another_16bit_integer/334);\n</code></pre>\n\n<p>edit: unsigned int, and you handle 0 on your own.</p>\n'}, {'answer_id': 41497, 'author': 'smh', 'author_id': 1077, 'author_profile': 'https://Stackoverflow.com/users/1077', 'pm_score': 2, 'selected': False, 'text': '<p>Bit shifts are usually very fast:</p>\n\n<pre><code>y = 0xFF3B * (int32_t) x &gt;&gt; 16;\n</code></pre>\n\n<p>This is probably better written as:</p>\n\n<pre><code>y = (0.997 * 0x10000) * (int32_t)x &gt;&gt; 16;\n</code></pre>\n\n<p>A good compiler will generate equivalent output.</p>\n\n<p>If your integers are signed, the constants should be changed to 0x8000 and 15. </p>\n'}, {'answer_id': 4758603, 'author': 'Rocketmagnet', 'author_id': 55934, 'author_profile': 'https://Stackoverflow.com/users/55934', 'pm_score': 1, 'selected': False, 'text': "<p>Here is a very fast way to do this operation:</p>\n\n<pre><code>a = b * 0.99609375;\n</code></pre>\n\n<p>It's similar to what you want, but it's <em>much</em> faster.</p>\n\n<pre><code>a  = b;\na -= b&gt;&gt;8;\n</code></pre>\n\n<p>Or even faster using a trick that only works on little endian systems, like the PIC.</p>\n\n<pre><code>a  = b;\na -= *((int8*)((&amp;b)+1));\n</code></pre>\n\n<p>Off the top of my head, this comes down to the following assembler on a PIC18:</p>\n\n<pre><code>; a = b\nMOVFF 0xc4, 0xc2\nNOP\nMOVFF 0xc5, 0xc3\nNOP\n\n; a -= *((int8*)((&amp;b)+1));\nMOVF  0xc5, w\nSUBWF 0xc2, f\nBTFSC STATUS, C\nDECF  0xc\n</code></pre>\n"}]
['https://Stackoverflow.com/questions/27405', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/609/']