SparkFun Electronics Commentsurn:uuid:214d0e4e-f1b1-d287-ce26-ac5b4c9f82492024-03-29T06:53:07-06:00SparkFun ElectronicsCustomer #656192 on Enginursday: DivisibilityCustomer #656192urn:uuid:2ed87467-211b-6271-8a43-e2f78178ab532015-03-02T12:28:34-07:00<p>I know I'm a bit late to the discussion, but there's a trick to the division-by-7 thing, too.<p>It requires that you memorize 1/7th as a decimal, which is 0.142857 (repeating all six post-decimal digits). Do integer division, then the decimal fraction is always the rotating sequence of those digits, starting with the n-th largest of the digits, where "n" is the integer remainder. So R1 is +0.142857, R2 is +0.285714, R3 is +0.428571, R4 is +0.571428, R5 is +0.714285, R6 is +0.857142. So as long as you can remember the set {1,4,2,8,5,7} and can non-destructively re-sort the set into ascending order, you can divide by 7.</p></p>
jonored on Enginursday: Divisibilityjonoredurn:uuid:7055c820-c4af-f634-b011-843af68279612015-02-27T09:08:48-07:00<p>Worth note that for the hex and octal versions of these, iterating over the digits in the number is as simple as doing i>>=3 or i>>=4 and i & 0xF or i & 0x7 - which is basically the same cost as the string conversion, but without the memory penalty and you're already at linear in the number of digits, and shifts and bitwise-and are usually cheap.</p>
GeoffreyF on Enginursday: DivisibilityGeoffreyFurn:uuid:326f484a-fafa-0d9e-d95c-6bc1e54b8c8d2015-02-27T08:06:05-07:00<p>About Octal ... Octal was popular in instruction sets that were based on groups of 3. This was useful when symbolic debuggers were not available, screens were small, printers were slow. Using a PDP-11 Reference card (which was necessary for the same reasons) - here are examples. It had eight registers, so that was a single octal digit in an instruction. There were eight "modes" such as auto increment, "Deferred", use as an address, index (use with a constant added to the register). "Deferred" was an odd value, not deferred was even. So the Clear or Clr instruction was 00 50 MR, in octal defining the mode or use of the register, then the register. Mov was 01 SS DD with the mode and register defined in the respective octal digits. For "banging two stones together" - it was very convenient and an experienced assembly language programmer could read an octal dump as easily as a not commented page of code. There were even certain "gambits" of coding which could be recognized, so one could figure things out just by using bit switches on the front panel and cycling through the memory one word at a time.</p>
joesugar on Enginursday: Divisibilityjoesugarurn:uuid:3adea0df-a8cf-7808-801a-98be9aa4d94f2015-02-27T05:32:08-07:00<p>This is the best explanation of this procedure I've seen.</p>
ADI on Enginursday: DivisibilityADIurn:uuid:a5be8cdb-02d3-2670-25ce-540bec6d3e1c2015-02-26T21:54:57-07:00<p>Great discussion, however, I avoid division when multiplication can perform the same job, and much faster.
eg. dividing by 3 is the same as multiplying by 1/3 = 0.330 or your equivalent scaled integer fraction.
eg. dividing by 5 is the same as multiplying by 1/5 = 0.200 or your equivalent scaled integer fraction.
eg. dividing by 7 is the same as multiplying by 1/7 = 0.142 or your equivalent scaled integer fraction.
This works great when the multiplier is a constant which can be calculated with a calculator, as you write your code.
If your original divisor is only known at runtime, then it becomes more of a job to calculate your scaled integer multiplier.
You can get away without division in a lot of cases. Perhaps you all already know this, but then again, maybe not. Cheers</p>
TheCentaur on Enginursday: DivisibilityTheCentaururn:uuid:a9f836a3-7a73-f3b4-8b75-074ad8d46a382015-02-26T18:30:46-07:00<p>Love math and tricks likes this. However, way back in my High School days, we had access to an old Univac Solid State 90.... it used Bi-Quinary coding. 5.4.2.1 Somehow I dont think the tricks would work so well with that. ;)</p>
Ted M on Enginursday: DivisibilityTed Murn:uuid:d28b8f86-cb55-3367-098f-642b61f329972015-02-26T18:26:53-07:00<p>If you like that, you'll like the cube root trick: you can quickly determine the cube root of any two digit number that has been cubed by looking at the first 3 digits and the last digit of the answer. I'll leave it to the reader to figure out how.</p>
dwc309 on Enginursday: Divisibilitydwc309urn:uuid:a52f81b4-891a-3b69-4784-d9a5ba6fe1c72015-02-26T15:42:12-07:00<p>I didn't know division by 9 worked like that. It makes sense though because division by 3 works the same way..</p>
tetsujin on Enginursday: Divisibilitytetsujinurn:uuid:72c1ce0f-a925-b6c4-0348-947d905c294d2015-02-26T14:21:45-07:00<p>You could still possibly come out ahead since the architecture doesn't natively support integer division.
For instance: you don't need to actually sum the digits repeatedly. You can sum them once, mod 3:<pre><code>unsigned long x = some_value;
unsigned char mod_result = 0;
while (x) {
hex_digit = (x & 0x0f);
x = x >> 4;
switch (hex_digit) {
case 1:
case 4:
case 7:
case 0xa:
case 0xd:
// ((hex_digit * 16^d) % 3 = 1) for any positive integer (d)
// Because (hex_digit % 3 =1), and
// (hex_digit * 16 % 3) = ((hex_digit * 15) + hex_digit) % 3
// which equals (hex_digit % 3) (since (x * 15 % 3) = 0 for any x)
mod_result += 1;
break;
case 2:
case 5:
case 8:
case 0xb:
case 0xe:
mod_result += 2;
break;
}
if (mod_result >= 3) mod_result -= 3;
}
</code></pre><p>This probably gives you a faster "x % 3" than you'd get from the compiler (it depends on how heavily it optimizes cases where the divisor is known at compile time), but the trade-off is that you are using more code space to do it. Like many optimizations, it becomes a question of how badly you need this one specific operation to be fast. (The above method could also be used for mod 7, by taking three bits at a time, or mod 15, by taking four bits at a time, and adjusting the switch statement accordingly)</p><p>On an architecture with integer division implemented in hardware, it's less likely the above method would be worth using. But on AVR it should be faster than an actual division algorithm - the switch statement could be implemented as a jump table, so the whole thing would take roughly 35 instruction cycles per hex digit, and probably a couple hundred bytes of instruction storage.</p></p>
Plinth on Enginursday: DivisibilityPlinthurn:uuid:9cacc492-a675-d215-cdef-e13f42ea52662015-02-26T12:51:40-07:00<p>I loved division by 9. You sum the digits and see if that's divisible by 9.
The cool thing about it is that this is fully generalizable to any base.
So if you have base n, you can do divisibility by n-1 by summing the digits in base n.<p>Divisibility by 7? Take your number in octal and sum the digits. If the resulting number is divisible by 7, the original number was divisible by 7.</p><p>When I was in 7th grade, we learned the easy division rules and the teacher had them up on a bulletin board. For 7 there was a '?'. After I had worked this method out, I made a point to find out if she was still working in the district (she was) and sent her a letter with my results.</p></p>
scicior on Enginursday: Divisibilitysciciorurn:uuid:33dd6eac-d22f-d2f8-b2e0-e222f9467eee2015-02-26T11:49:56-07:00<p>Back in 7th grade I was arguing with a friend what was more elegant; hex or octal. After he pointed out that after memorizing the binary representation of the 8080A instruction set, for the move, add, compare, etc, instructions, some of 3 bit fields (which can easily be represented in octal) always map to the same register. Oh, and using a 7447 TTL chip to represent a hex number on a 7 segment display just looked stupid.... couldn't argue with that.
- Steve</p>
Byron J. on Enginursday: DivisibilityByron J.urn:uuid:0ecb0679-0897-7b14-7e1d-b456981e9b062015-02-26T10:47:16-07:00<p>I knew I shoulda just said "DEC!"</p>
Byron J. on Enginursday: DivisibilityByron J.urn:uuid:a202b7b9-073c-27a1-5eaf-d6c14e6c40f12015-02-26T10:40:54-07:00<p>These tests are actually pretty cumbersome to implement in code, since you've have to convert numbers to strings, then cycle through the strings to compose the sums. Unless you're working in COBOL, where numbers are intrinsically strings, it's not terribly efficient.<p>Where it is efficient is in the programer's brain while designing and debugging software. If you need to recognize particular multiples, it's easier if you can just "see" them, than to have to pull out a calculator.</p><p>The thing it does help with is that you can occur in the programmer's noggin</p></p>
Customer #648854 on Enginursday: DivisibilityCustomer #648854urn:uuid:0e6aa414-6023-2ad1-55da-d64524a48d932015-02-26T10:31:37-07:00<p>Nice post, I've been teaching my daughter the divisible by 3 trick.<p>One minor point. I think the PDP-8 was made by Digital Equipment Corp. (not Digital Electronics Corp).</p></p>
Byron J. on Enginursday: DivisibilityByron J.urn:uuid:b9a0a6c0-fd6c-b1c3-999c-2e45a6f91f062015-02-26T10:30:06-07:00<p>Yup - you're right. Now fixed.<p>I cloned & mutated the decimal figure to make the hex. I remembered to change all the numbers, but forgot the text.</p></p>
Customer #394180 on Enginursday: DivisibilityCustomer #394180urn:uuid:67893f86-24df-1f50-c4a3-e3b2adae79f32015-02-26T10:17:51-07:00<p>Totally agree. Using integers instead of floating point is one of the best things that you can do to make your code faster, portable and more reliable. In every control system I've programmed, the data comes in as an integer count value from an ADC converter, or as a digital bit value. Nothing comes in floating point. Newbies are eager to immediately turn it into floating point engineering units, not realizing that they are introducing inaccuracies and slowing everything down.<p>Some may argue that using floating point constants in source code makes it easier to understand. The same can be accomplished with symbolic constants that are defined to have the appropriate integer or scaled integer value.</p><p>For the actual control logic, the cleanest data flow is to take the integer data from the ADC, process it in the integer domain, put the result out as an integer to the DAC and only convert it to floating point for display.</p><p>If fractions are needed, there's scaled integer.</p></p>
M-Short on Enginursday: DivisibilityM-Shorturn:uuid:029eb04d-f79b-681f-cbeb-f7e43d42c76b2015-02-26T09:44:04-07:00<p>I actually remember learning this in school at some point as well. I specifically remember the teacher saying that there is a method for 7, but it's easier to just divide it out. It always bothered me that I never knew how that one worked. As for 4 and 8 you just need to check that the last 2 or 3 numbers are divisible by 4 or 8 respectively, no need to divide your number by 2.</p>
OldFar-SeeingArt on Enginursday: DivisibilityOldFar-SeeingArturn:uuid:3fc47b97-0488-6159-2cc2-7f8bb70499a32015-02-26T09:40:37-07:00<p>Thank you for the interesting topic. I've learned and forgotten much of this over the years. In particular I enjoyed the comments about the generalization of the method that @Blaise Pascal posted.<p>Something that caught my eye however was the third paragraph about the utility of integer math on small embedded controllers; this is probably worth an enginursday blog. I wanted to only use floating point when I started out programming PICs but was enlightened by my mentor of how to use integer math instead. After a while it became second nature. When I began to use compilers instead of assembly language, I still applied integer math and still do even though the compiler provided floating point libraries and my simple programs on large PIC32 chips had room and speed for floating point. Nothing religious here, it's just a way of seeing and solving problems. Horses for courses.</p></p>
XLT_Frank on Enginursday: DivisibilityXLT_Frankurn:uuid:3dc92c5d-d741-bd0d-17b3-06c851de59252015-02-26T09:31:53-07:00<p>How do you effectively use this to your advantage with programming? All of these "test" take instruction time, correct?</p>
NorthStreetLabs on Enginursday: DivisibilityNorthStreetLabsurn:uuid:ec568d16-d4a6-8b57-3a18-8bd69aac161f2015-02-26T09:10:31-07:00<p>In figure 2, you conclude<blockquote>
<p>0xC (Decimal 12) is divisible by 3, thus 0x5CAF is <strong>not</strong> divisible by 3.</p>
</blockquote><p>I believe you meant to say the opposite, because 0x5CAF is indeed divisible by 3, it becomes 0x1EE5.</p></p>
boba on Enginursday: Divisibilitybobaurn:uuid:7fbfaac8-c95a-980a-bbe5-2269b76e55c02015-02-26T08:39:21-07:00<p>You make it look so easy <blush>.</p>
Blaise Pascal on Enginursday: DivisibilityBlaise Pascalurn:uuid:9dd48b1e-4c20-a789-ef25-3c556faac6772015-02-26T08:03:43-07:00<p>The key here is that you are taking your number N and breaking it down into two numbers a and b such that N = 10a+b. If you work mod 7, this becomes<p>N = 10a + b (mod 7)
N = (7+3)a + b (mod 7)
N = 7a + 3a + b (mod 7)
N = 3a + b (mod 7)</p><p>So 3a+b gives the same remainder divided by 7 as N, and that's your procedure.</p><p>The same reasoning shows why it works for any divisor less than ten. In particular, it shows why the casting out 9's procedure works (or, why in octal, the casting out 7's procedure works for divisibility by 7).</p><p>We can also show why the divisibility rule for 3 works:</p><p>N = 10a+b (mod 3)
N = (3<em>3+1)a + b (mod 3)
N = (3</em>3)a + a + b (mod 3)
N = a + b (mod 3)</p><p>so N and a+b have the same remainder, mod 3. So you can just add the final digit to the others to get a smaller number with the same remainder, etc.</p><p>It's also generalizable to other bases and divisors: In base B, choose n such that n divides B-1 (so B = kn+1 for some k):</p><p>N = aB + b (mod n)
N = a(kn+1) + b (mod n)
N = akn + a + b (mod n)
N = a + b (mod n)</p><p>So the "sum the digits" rule works for divisibility tests in hexadecimal for 3, 5, and 15 (the divisors of 15).</p><p>More generally, if B = kn+l, then the rule becomes "multiply a by l, then add b"</p></p>
Blaise Pascal on Enginursday: DivisibilityBlaise Pascalurn:uuid:449ea657-16fa-eeda-1624-e9b83cada2b12015-02-26T07:45:29-07:00<p>To tie together two of the difficult patches in this article... If you sum the octal digits and get a number divisible by 7, then the original number is divisible by 7.<p>For example, 1015 (decimal) = 01767 in octal, and 01+07+06+07 = 025 (octal), and 02+05 = 07 (octal), so 01767 (octal) (or 1015 decimal) is divisible by 7. Which it is. 442 decimal is 0672, and 6+7+2 = 017 (octal), which reduces to 1+7 = 010 (octal), which is not divisible by 7, so 442 is not divisible by 7.</p></p>
boba on Enginursday: Divisibilitybobaurn:uuid:78a1247d-e41d-380c-fff8-acb1f9a996a72015-02-26T07:37:49-07:00<p>To show divisibility by 7, take all the digits except the rightmost, multiply that number by 3, and add the rightmost digit. Repeat until the number is recognizably divisible by 7.<p>Example: 42 - multiply 4 by 3 and add 2, you get 14. Multiply 1 by 3 and add 4 to get 7.</p><p>Example: 105 - multiply 10 by 3 and add 5 to get 35. Multiply 3 by 3 and add 5 to get 14.</p><p>This method occurred to me in 3rd grade. I've attempted a mathematical proof a few times but haven't succeeded. (I don't know how to apply the fact that something pertains only to integers, and not to reals, in a proof.)</p><p>I couldn't prove it, but I was able to generalize it: to find if a number is divisible by a number, n, less than ten, take the upper digits, multiply them by (10 - n) and add the rightmost digit.</p></p>