整数の2進表現が回文であるかどうかを確認するにはどうすればよいですか?
18 に答える
うまくいけば正しい:
_Bool is_palindrome(unsigned n)
{
unsigned m = 0;
for(unsigned tmp = n; tmp; tmp >>= 1)
m = (m << 1) | (tmp & 1);
return m == n;
}
それを行う言語を指定していないので、ここにいくつかの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;
}
あなたの10001のもののために修正された編集。
文字を含む256行のグラフを作成し、文字を少し反転させます。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);
}
以下は、任意の符号なしタイプに適応できる必要があります。(符号付き型のビット演算は問題を伴う傾向があります。)
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;
}
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;
}
私は常に文字列で動作する回文関数を持っています。これは、Javaの場合など、そうでない場合はtrueを返し、そうでない場合はfalseを返します。私がする必要がある唯一のことは次のようなものです:
int number = 245;
String test = Integer.toString(number, 2);
if(isPalindrome(test)){
...
}
この質問が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;
一般的なバージョン:
#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";
}
最善のアプローチは、最後から始めて内側に向かって作業することだと思います。つまり、最初のビットと最後のビット、2番目のビットと最後から2番目のビットなどを比較します。ここで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;
}
失敗を報告するのも良い場合があります。
何らかの形で、または他のビットパターンを分析することによって、それを行うための明白な方法について、ここには多くの素晴らしい答えがあります。しかし、数学的な解決策はあるのだろうかと思いました。私たちが利用するかもしれない古風な数の特性はありますか?
だから私は少し数学で遊んだが、答えは最初から本当に明白だったはずだ。すべての2進回文数が奇数またはゼロでなければならないことを証明するのは簡単です。それは私がそれで得ることができた限りです。
少しの研究では、10進回文に対するそのようなアプローチは示されていなかったため、非常に難しい問題であるか、正式なシステムでは解決できません。後者を証明するのは面白いかもしれません...
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;
}
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;
}
- バイナリパリンドロームについては、PalInt(i、1)を呼び出します
- オクタルパリンドロームについては、PalInt(i、3)を呼び出します
- 16回文の場合はPalInt(i、4)を呼び出します
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();
}
#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;
}
以下の解決策はPythonで機能します:
def CheckBinPal(b):
b=str(bin(b))
if b[2:]==b[:1:-1]:
return True
else:
return False
ここで、bは整数です
Clangを使用している場合は、いくつか__builtin
のを利用できます。
bool binaryPalindrome(const uint32_t n) {
return n == __builtin_bitreverse32(n << __builtin_clz(n));
}
注意すべきことの1つは、それ__builtin_clz(0)
が未定義であるため、ゼロをチェックする必要があるということです。Clang(次世代mac)を使用してARMでコンパイルしている場合、これは、reverseおよびclz(コンパイラエクスプローラー)のアセンブリ命令を利用します。
clz w8, w0
lsl w8, w0, w8
rbit w8, w8
cmp w8, w0
cset w0, eq
ret
x86には、clz(一種)の説明がありますが、元に戻すことはできません。それでも、Clangは、ターゲットアーキテクチャを逆にするために可能な限り最速のコードを出力します。
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))