8

How to check if the binary representation of an integer is a palindrome?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
yesraaj
  • 46,370
  • 69
  • 194
  • 251
  • 3
    Is 10001 a palindrome? Or does it have to be a full byte- 00100100? Or does it have to be a full int- 00000000 00000001 10000000 00000000? – jmucchiello May 10 '09 at 18:22
  • 4
    So `0110` *isn't* a palindrome, because it's really `110`, right? Which implies that all non-zero palindromes are odd. – Keith Thompson May 15 '13 at 18:48

18 Answers18

16

Hopefully correct:

_Bool is_palindrome(unsigned n)
{
    unsigned m = 0;

    for(unsigned tmp = n; tmp; tmp >>= 1)
        m = (m << 1) | (tmp & 1);

    return m == n;
}
Christoph
  • 164,997
  • 36
  • 182
  • 240
12

Since you haven't specified a language in which to do it, here's some C code (not the most efficient implementation, but it should illustrate the point):

/* flip n */
unsigned int flip(unsigned int n)
{
    int i, newInt = 0;
    for (i=0; i<WORDSIZE; ++i)
    {
        newInt += (n & 0x0001);
        newInt <<= 1;
        n >>= 1;
    }
    return newInt;
}

bool isPalindrome(int n)
{
    int flipped = flip(n);
    /* shift to remove trailing zeroes */
    while (!(flipped & 0x0001))
        flipped >>= 1;
    return n == flipped;
}

EDIT fixed for your 10001 thing.

rlbond
  • 65,341
  • 56
  • 178
  • 228
3

Create a 256 lines chart containing a char and it's bit reversed char. given a 4 byte integer, take the first char, look it on the chart, compare the answer to the last char of the integer. if they differ it is not palindrome, if the are the same repeat with the middle chars. if they differ it is not palindrome else it is.

Liran Orevi
  • 4,755
  • 7
  • 47
  • 64
2

Plenty of nice solutions here. Let me add one that is not the most efficient, but very readable, in my opinion:

/* Reverses the digits of num assuming the given base. */
uint64_t
reverse_base(uint64_t num, uint8_t base)
{
  uint64_t rev = num % base;

  for (; num /= base; rev = rev * base + num % base);

  return rev;
}

/* Tells whether num is palindrome in the given base. */
bool
is_palindrome_base(uint64_t num, uint8_t base)
{
  /* A palindrome is equal to its reverse. */
  return num == reverse_base(num, base);
}

/* Tells whether num is a binary palindrome. */ 
bool
is_palindrome_bin(uint64_t num) 
{
  /* A binary palindrome is a palindrome in base 2. */
  return is_palindrome_base(num, 2);
}
Stephan202
  • 59,965
  • 13
  • 127
  • 133
1
int palidrome (int num) 
{ 
  int rev = 0; 
  num = number; 
  while (num != 0)
  { 
    rev = (rev << 1) | (num & 1); num >> 1; 
  }

  if (rev = number) return 1; else return 0; 
}
Lucas Trzesniewski
  • 50,214
  • 11
  • 107
  • 158
  • Please make sure you properly format your answers so they are readable. All code should be indented 4 spaces. Thanks! – mdewitt Sep 30 '14 at 22:17
1

The following should be adaptable to any unsigned type. (Bit operations on signed types tend to be fraught with problems.)

bool test_pal(unsigned n)
{
  unsigned t = 0;

  for(unsigned bit = 1; bit && bit <= n; bit <<= 1)
    t = (t << 1) | !!(n & bit);

  return t == n;
}
Dingo
  • 3,305
  • 18
  • 14
  • +1; my answer uses the same algorithm, but instead of shifting a mask left, it shifts the value n right – Christoph Jun 22 '09 at 23:57
0
    public static bool IsPalindrome(int n) {
        for (int i = 0;  i < 16; i++) {
            if (((n >> i) & 1) != ((n >> (31 - i)) & 1)) {
                return false;
            }
        }
        return true;
    }
0
bool PaLInt (unsigned int i, unsigned int bits)
{
    unsigned int t = i;
    unsigned int x = 0;
    while(i)
    {
        x = x << bits;        
        x = x | (i & ((1<<bits) - 1));
        i = i >> bits;
    }
    return x == t;
}
  1. Call PalInt(i,1) for binary pallindromes
  2. Call PalInt(i,3) for Octal Palindromes
  3. Call PalInt(i,4) for Hex Palindromes
0

In JAVA there is an easy way if you understand basic binary airthmetic, here is the code:

    public static void main(String []args){
        Integer num=73;
        String bin=getBinary(num);
        String revBin=reverse(bin);
        Integer revNum=getInteger(revBin);

        System.out.println("Is Palindrome: "+((num^revNum)==0));

     }

     static String getBinary(int c){
         return Integer.toBinaryString(c);
     }

     static Integer getInteger(String c){
         return Integer.parseInt(c,2);
     }

     static String reverse(String c){
         return new StringBuilder(c).reverse().toString();
     }
Wajahat
  • 1,593
  • 3
  • 20
  • 47
  • This is an interview question to test you about bitwise operations, and you are not meant to to use String or StringBuilder functions – GaRRaPeTa Sep 16 '14 at 21:05
0
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
    unsigned int n = 134217729;
    unsigned int bits = floor(log(n)/log(2)+1);
    cout<< "Number of bits:" << bits << endl;
    unsigned int i=0;
    bool isPal = true;
    while(i<(bits/2))
    {
        if(((n & (unsigned int)pow(2,bits-i-1)) && (n & (unsigned int)pow(2,i))) 
                                         ||    
        (!(n & (unsigned int)pow(2,bits-i-1)) && !(n & (unsigned int)pow(2,i))))
        {
            i++;
            continue;
        }
        else
        {
            cout<<"Not a palindrome" << endl;
            isPal = false;
            break;
        }
}

    if(isPal)
        cout<<"Number is binary palindrome" << endl;
}
cppcoder
  • 22,227
  • 6
  • 56
  • 81
0

The solution below works in python:

def CheckBinPal(b): b=str(bin(b)) if b[2:]==b[:1:-1]: return True else: return False

where b is the integer

Divyam
  • 1
0

If you're using Clang, you can make use of some __builtins.

bool binaryPalindrome(const uint32_t n) {
  return n == __builtin_bitreverse32(n << __builtin_clz(n));
}

One thing to note is that __builtin_clz(0) is undefined so you'll need to check for zero. If you're compiling on ARM using Clang (next generation mac), then this makes use of the assembly instructions for reverse and clz (compiler explorer).

clz     w8, w0
lsl     w8, w0, w8
rbit    w8, w8
cmp     w8, w0
cset    w0, eq
ret

x86 has instructions for clz (sort of) but not reversing. Still, Clang will emit the fastest code possible for reversing on the target architecture.

Indiana Kernick
  • 5,041
  • 2
  • 20
  • 50
0

Javascript Solution

function isPalindrome(num) {
  const binaryNum = num.toString(2);
  console.log(binaryNum)
  for(let i=0, j=binaryNum.length-1; i<=j; i++, j--) {
    if(binaryNum[i]!==binaryNum[j]) return false;
  }
  return true;
}

console.log(isPalindrome(0))
Vinit Khandelwal
  • 490
  • 8
  • 20
0

I always have a palindrome function that works with Strings, that returns true if it is, false otherwise, e.g. in Java. The only thing I need to do is something like:

int number = 245;
String test = Integer.toString(number, 2);
if(isPalindrome(test)){
   ...
}
rapfaria
  • 2,577
  • 2
  • 14
  • 14
  • 6
    You "always have a palindrome function"? Why exactly? – Hejazzman May 10 '09 at 18:38
  • 1
    Maybe you got me wrong. I mean that I have a palindrome function that works on Strings, and I can use it everywhere. Think once, use always. – rapfaria May 10 '09 at 18:40
  • 3
    The question is what is isPalindrome()'s implementation. But, specifically, with binary representations. – xanadont May 10 '09 at 18:42
  • 1
    String test = Integer.toString(number, 2); With this, the number will be represented in binary. The implementation is very simple. You loop till the middle of the String, and compare the char at the current position with the char on the respective position (test.length - current position). If they difer, you return false. When the loop is finished, you return true. =) – rapfaria May 10 '09 at 18:47
  • 1
    Raphael's answer makes complete sense, he just change the problem from working with binaries to working with a string, and solving if a string is a palindrome is fairly simple. The only caveat is that this question is tagged with c, c++ – Javier May 10 '09 at 18:54
  • 1
    In C, you just convert the int to an array of chars, using itoa() (or the more supported sprintf()). After this, you just follow the previous steps. Quite easy =) – rapfaria May 10 '09 at 19:03
  • I agree with your approach. "The binary representation of an integer" is actually a string, in the same way as "The decimal representation of an integer" or "The hex representation of an integer" are. So dividing the problem into first obtain the string and then tell if it's a palindrome is correct. – Daniel Daranas May 11 '09 at 12:40
0

I think the best approach is to start at the ends and work your way inward, i.e. compare the first bit and the last bit, the second bit and the second to last bit, etc, which will have O(N/2) where N is the size of the int. If at any point your pairs aren't the same, it isn't a palindrome.

bool IsPalindrome(int n) {
    bool palindrome = true;
    size_t len = sizeof(n) * 8;
    for (int i = 0; i < len / 2; i++) {
        bool left_bit = !!(n & (1 << len - i - 1));
        bool right_bit = !!(n & (1 << i));
        if (left_bit != right_bit) {
            palindrome = false; 
            break;
        }
    }
    return palindrome;
}
i_am_jorf
  • 53,608
  • 15
  • 131
  • 222
  • Doesn't compile: bool right_bit = !!(n & (1 << i); is missing a closing parentheses. Won't this will break if there are leading zeros e.g: 17? – dirkgently May 10 '09 at 19:02
  • But it is strange we used the same versions almost (including naming). In fact, I ran your code against mine to determine differences and compiler errors. – dirkgently May 10 '09 at 19:11
  • Fixed the missing paren. I am assuming, since the OP didn't specify, that the entire bitfield of the int must be a palindrome, not that we are ignoring leading zeros. But now that you mention it, it might make sense to do it that way. – i_am_jorf May 10 '09 at 19:26
  • sizeof(n); gives you the size in bytes, you need the size in bits. – dirkgently May 10 '09 at 20:58
0

A generic version:

#include <iostream>
#include <limits>
using namespace std;

template <class T>
bool ispalindrome(T x) {
    size_t f = 0, l = (CHAR_BIT * sizeof x) - 1;
    // strip leading zeros
    while (!(x & (1 << l))) l--;
    for (; f != l; ++f, --l) {
        bool left = (x & (1 << f)) > 0; 
        bool right = (x & (1 << l)) > 0;
        //cout <<  left << '\n';
        //cout <<  right << '\n';
        if (left != right) break;
    }
    return f != l;
}       

int main() {
    cout << ispalindrome(17) << "\n";
}
dirkgently
  • 108,024
  • 16
  • 131
  • 187
0

Sometimes it's good to report a failure too;

There are lots of great answers here about the obvious way to do it, by analyzing in some form or other the bit pattern. I got to wondering, though, if there were any mathematical solutions? Are there properties of palendromic numbers that we might take advantage of?

So I played with the math a little bit, but the answer should really have been obvious from the start. It's trivial to prove that all binary palindromic numbers must be either odd or zero. That's about as far as I was able to get with it.

A little research showed no such approach for decimal palindromes, so it's either a very difficult problem or not solvable via a formal system. It might be interesting to prove the latter...

Chris Arguin
  • 11,850
  • 4
  • 34
  • 50
  • "all binary palindromic numbers must be either odd or zero" 0110 is neither odd nor zero, but can be considered a palindrome in base 2, it depends if you allow a palindrome to have leading zeros. – Eloff Oct 25 '10 at 18:57
  • Decimal palindromes have exactly the same approach; all palindromes must not end in a 0 or be 0. – ysth Dec 22 '10 at 09:56
0

I know that this question has been posted 2 years ago, but I have a better solution which doesn't depend on the word size and all,

int temp = 0;
int i = num;
while (1)
{ // let's say num is the number which has to be checked
    if (i & 0x1)
    {
        temp = temp + 1;
    }
    i = i >> 1;
    if (i) {
        temp = temp << 1;
    }   
    else   
    {
        break;
    }
}   

return temp == num;
Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
brut3f0rc3
  • 1,173
  • 4
  • 13
  • 19