【问题标题】:How to check if the binary representation of an integer is a palindrome?如何检查整数的二进制表示是否是回文?
【发布时间】:2010-10-25 03:37:25
【问题描述】:

如何检查整数的二进制表示是否为回文?

【问题讨论】:

  • 10001 是回文吗?或者它必须是一个完整的字节 - 00100100?还是必须是完整的int- 00000000 00000001 10000000 00000000?
  • 所以0110不是回文,因为它真的是110,对吧?这意味着所有非零回文都是奇数。

标签: c++ c binary integer palindrome


【解决方案1】:

希望正确:

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

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

    return m == n;
}

【讨论】:

    【解决方案2】:

    由于您尚未指定执行此操作的语言,这里有一些 C 代码(不是最有效的实现,但它应该说明这一点):

    /* 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 已为您的 10001 事物修复。

    【讨论】:

    • 我喜欢这个解决方案,因为它很简单。在代码和算法上都非常清楚。
    • 整数中的位数(或您想要使用的任何数据类型)
    • 这段代码进入了isPalindrome(0x0)的无限循环;而且我认为它有一个 off by 1 错误,它将 newInt 移动了太多
    【解决方案3】:

    创建一个包含一个字符的 256 折线图,它是位反转字符。 给定一个 4 字节整数, 取第一个字符,在图表上查看,将答案与整数的最后一个字符进行比较。 如果它们不同,则不是回文,如果它们与中间字符相同,则重复。 如果它们不同,则不是回文,否则它是。

    【讨论】:

    • 这不能很好地扩展——你要为一个 32 位整数使用 20 亿折线图吗?
    • 你不需要 - 你只需要一次比较字节
    • 啊,当然。当然,这不像他澄清的那样有效。
    • 这假定数字是对齐的。 101 是回文,但 0000 0000 0000 0101 不是。
    【解决方案4】:

    这里有很多不错的解决方案。在我看来,让我添加一个不是最有效但非常可读的:

    /* 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);
    }
    

    【讨论】:

      【解决方案5】:

      以下内容应该适用于任何无符号类型。 (有符号类型的位操作往往充满问题。)

      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;
      }
      

      【讨论】:

      • +1;我的答案使用相同的算法,但不是向左移动掩码,而是向右移动值 n
      【解决方案6】:
      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; 
      }
      

      【讨论】:

      • 请确保您的答案格式正确,以便阅读。所有代码应缩进 4 个空格。谢谢!
      【解决方案7】:

      我总是有一个与字符串一起使用的回文函数,如果是则返回 true,否则返回 false,例如在爪哇。我唯一需要做的就是:

      int number = 245;
      String test = Integer.toString(number, 2);
      if(isPalindrome(test)){
         ...
      }
      

      【讨论】:

      • 你“总是有回文函数”?为什么?
      • 也许你误会了。我的意思是我有一个适用于字符串的回文函数,我可以在任何地方使用它。一次思考,永远使用。
      • 问题是什么是isPalindrome() 的实现。但是,具体来说,使用二进制表示。
      • 字符串测试 = Integer.toString(number, 2);这样,数字将以二进制表示。实现非常简单。您循环到字符串的中间,并将当前位置的字符与相应位置的字符(test.length - 当前位置)进行比较。如果它们不同,则返回 false。循环结束后,返回 true。 =)
      • Raphael 的回答完全有道理,他只是将问题从使用二进制文件更改为使用字符串,并且解决字符串是否是回文非常简单。唯一需要注意的是,这个问题被标记为 c, c++
      【解决方案8】:

      通用版本:

      #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";
      }
      

      【讨论】:

        【解决方案9】:

        我认为最好的方法是从末端开始向内工作,即比较第一位和最后一位、第二位和倒数第二位等,这将有 O(N/2 ) 其中 N 是 int 的大小。如果你的对在任何时候都不相同,那么它就不是回文。

        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;
        }
        

        【讨论】:

        • 不编译:bool right_bit = !!(n & (1
        • 但奇怪的是我们几乎使用了相同的版本(包括命名)。事实上,我针对我的代码运行了你的代码以确定差异和编译器错误。
        • 修复了缺失的括号。我假设,因为 OP 没有指定,int 的整个位域必须是回文,而不是我们忽略前导零。但是既然您提到了它,那么这样做可能是有意义的。
        • sizeof(n);给你以字节为单位的大小,你需要以位为单位的大小。
        【解决方案10】:

        有时报告失败也很好;

        通过以某种形式或其他方式分析位模式,这里有很多关于显而易见的方法的很好的答案。不过,我想知道是否有任何数学解决方案?有没有我们可以利用的古数的性质?

        所以我稍微玩了一下数学,但答案应该从一开始就很明显。证明所有二进制回文数必须是奇数或零是微不足道的。这是我能做到的。

        一项小研究表明,对于十进制回文,没有这种方法,因此它要么是一个非常困难的问题,要么无法通过正式系统解决。证明后者可能会很有趣......

        【讨论】:

        • "所有二进制回文数必须是奇数或零" 0110 既不是奇数也不是零,但可以被视为以 2 为底的回文数,这取决于您是否允许回文数具有前导零。
        • 十进制回文具有完全相同的方法;所有回文都不能以 0 或 0 结尾。
        【解决方案11】:
            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;
            }
        

        【讨论】:

          【解决方案12】:
          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. 为二进制回文串调用 PalInt(i,1)
          2. 为八进制回文调用 PalInt(i,3)
          3. 为十六进制回文调用 PalInt(i,4)

          【讨论】:

            【解决方案13】:

            我知道这个问题已在 2 年前发布,但我有一个更好的解决方案,它不依赖于字数大小等等,

            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;
            

            【讨论】:

              【解决方案14】:

              在 JAVA 中有一个简单的方法,如果你了解基本的二进制计算,这里是代码:

                  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();
                   }
              

              【讨论】:

              • 这是一道面试题,旨在测试你的位运算,你不会使用 String 或 StringBuilder 函数
              【解决方案15】:
              #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;
              }
              

              【讨论】:

                【解决方案16】:

                以下解决方案适用于 python:

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

                其中b是整数

                【讨论】:

                  【解决方案17】:

                  如果你使用 Clang,你可以使用一些 __builtins。

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

                  需要注意的一点是__builtin_clz(0) 未定义,因此您需要检查是否为零。如果您使用 Clang(下一代 mac)在 ARM 上进行编译,那么这将使用 reverse 和 clz (compiler explorer) 的汇编指令。

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

                  x86 有 clz 的指令(有点),但没有反转。尽管如此,Clang 仍会发出尽可能快的代码以在目标架构上进行逆向。

                  【讨论】:

                    【解决方案18】:

                    Javascript 解决方案

                    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))
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2011-03-06
                      • 2011-02-11
                      • 2018-05-09
                      • 1970-01-01
                      • 2021-04-05
                      • 1970-01-01
                      • 1970-01-01
                      • 2011-12-09
                      相关资源
                      最近更新 更多