Testwiki:Reference desk/Archives/Computing/2017 January 15
Template:Error:not substituted
|- ! colspan="3" align="center" | Computing desk |- ! width="20%" align="left" | < January 14 ! width="25%" align="center"|<< Dec | January | Feb >> ! width="20%" align="right" |Current desk > |}
| Welcome to the Wikipedia Computing Reference Desk Archives |
|---|
| The page you are currently viewing is a transcluded archive page. While you can leave answers for any questions shown below, please ask new questions on one of the current reference desk pages. |
January 15
Modular arithmetic with limited integer range
Let's say I'm using a programming language where integers range from to (inclusive) (for example, -2^31 to 2^31 - 1), and , , etc. What algorithm can I use to compute modulo , where ? Obviously the result will be expressible within the range of integers. Assume I don't have access to any larger integer type and values can't be promoted to a larger type at any point of the algorithm. 24.255.17.182 (talk) 21:06, 15 January 2017 (UTC)
- Why do you have 1 as a lower limit instead of 0? Anyway (a mod m)+(b mod m) mod m will do the job. Or for 2^31-1 as the upper limit one could use unsigned arithmetic with a range 0..2^32-1 for the add and modulo in (a+b) mod m. Dmcq (talk) 00:07, 16 January 2017 (UTC)
- (a mod m)+(b mod m) could still be larger than 2^32-1. 24.255.17.182 (talk) 01:11, 16 January 2017 (UTC)
- I assume that when you say "etc." you mean that if a calculation overflows then is added or subtracted to/from the result, the common behavior on 2's complement computers. In that case, if (a mod m)+(b mod m) cannot be represented, it will come out as a negative number. So just test if it is negative, and in that case, subtract m. This will underflow and you'll get the correct positive numebr. --69.159.60.210 (talk) 07:52, 16 January 2017 (UTC)
- If a and b are positive and less than 231 then their sum is less than 232, so unsigned(a mod m) + unsigned(b mod m) won't overflow. Even unsigned(a)+unsigned(b) won't overflow. -- BenRG (talk) 20:23, 17 January 2017 (UTC)
- (a mod m)+(b mod m) could still be larger than 2^32-1. 24.255.17.182 (talk) 01:11, 16 January 2017 (UTC)
Quote from Zeller's congruence: "The formulas rely on the mathematician's definition of modulo division, which means that −2 mod 7 is equal to positive 5. Unfortunately, the way most computer languages implement the remainder function, −2 mod 7 returns a result of −2". I once had to field-service 10,000 time lapse video recorders because the programmer used the wrong Modulo, causing them all to crash hard on a particular date. --Guy Macon (talk) 15:24, 16 January 2017 (UTC)
- However, since we were told we were being given positive numbers, that won't be an issue this time. --69.159.60.210 (talk) 19:13, 16 January 2017 (UTC)
- Not an expert, but I'm thinking you can arithmetic shift right each number, saving the first remainder R1, then saving R2 = that AND the second, then replacing R1 = R1 XOR with the second. (Hmmm, need to be very careful about that operation with negative numbers; not sure if this was right for them) Add the shifted numbers, getting 0.5a + 0.5b. If m is even, take (0.5a + 0.5b) mod 0.5m. Now do a arithmetic shift left to double this and put R1 back into the result. Add R2. You should not get an overflow, which only happens if you're taking FFFF + FFFF mod FFFF I think, and that's odd. For odd... well, that's the sticky part, isn't it? Maybe take (0.5a + 0.5b) mod (0.5m+0.5), which is 0.5 too low per m, plus (0.5a + 0.5b) div m, then do comparisons to bring it up or down by a single 0.5m unit, suitably adjusting the remainder? I'd have to write the program to find the bugs in that though! Wnt (talk) 15:09, 17 January 2017 (UTC)