-2

I want to create a method which given a number n and the number 16 and applies the modulus operator to them (n % 16). The thing which makes it hard for me is that I need to not use any of math operators (+, -, /, *, %).

Wazery
  • 15,394
  • 19
  • 63
  • 95
  • 3
    In general this won't be possible, but specifically for 16 (or powers of two) you can just mask, `n & 15`. Also fails on negative numbers – kalhartt Dec 14 '13 at 17:54
  • 2
    @kalhartt - assuming the integer representation is twos complement, and that there are no undefined behaviour issues, `n & 15` will give the correct modulous even for negative `n` - but not necessarily the same value as `n % 16`. Remainders are defined relative to division, so the result depends on the rounding used for the division, but modulous results are always non-negative. `-1 mod 16 == 15`, though `-1 rem 16` may be 15 or -1. Sorry, I can't be more specific as I don't know Ruby. –  Dec 14 '13 at 18:08
  • Why can't you use arithmetic operators? Why can't you simply use `%` and get on with more productive work? – mu is too short Dec 14 '13 at 19:01
  • Sure I would use % if it for work, but this is a coding challenge I stumbled at. – Wazery Dec 14 '13 at 19:04
  • @Steve314 can you explain? If we assume bit length much greater than the mask, then you can see `-5 & 15` is `11` which is neither 10 for division rounding to -inf nor 5 for division rounding to zero. – kalhartt Dec 14 '13 at 19:30
  • 1
    Nevermind, I'm an idiot. Just forgot its off by one. – kalhartt Dec 14 '13 at 19:38
  • @kalhartt - yes, you're off by one. For division rounding to -inf, it's `-5 rem 16 == 11` that equates to `-5 & 15 == 11`. –  Dec 14 '13 at 21:13

2 Answers2

4

Since 16 is 2^4 you can obtain the same result by truncating the value to the 4 least significant bits.

So:

x & 0xF is equivalent to x % 16

This is valid just because you are working with a power of two.

Jack
  • 131,802
  • 30
  • 241
  • 343
0

The key here is that 16 is a power of two, and so you can exploit the fact that computers utilise binary representations to achieve what you want with a bitwise operator.

Consider how multiples of 16 look when represented in binary:

0001 0000 // n = 16, n%16 = 0
0010 0000 // n = 32, n%16 = 0 
0011 0000 // n = 48, n%16 = 0
0100 0000 // n = 64, n%16 = 0

Now take a look at some numbers for which n % 16 would be non-zero:

0000 0111 // n = 7,  n%16 = 7
0001 0111 // n = 23, n%16 = 7
0010 0001 // n = 33, n%16 = 1
0100 0001 // n = 65, n%16 = 1

Notice that the remainder is simply the least significant 4 bits (nibble) - therefore we simply need to construct a bitwise expression that will keep these bits intact, whilst masking all other bits to zero. This can be achieved by performing a bitwise AND operation with the binary value 15:

x = n & 0xF
jprice
  • 9,755
  • 1
  • 28
  • 32
  • 1
    A group of 4 bits is traditionally called a nibble, a byte is (usually) 8 bits. –  Dec 14 '13 at 18:12