Cで特定の数値が偶数か奇数かを確認するにはどうすればよいですか?
Cで特定の数値が偶数か奇数かを確認するにはどうすればよいですか?
回答:
モジュロ(%)演算子を使用して、2で除算するときに余りがあるかどうかを確認します。
if (x % 2) { /* x is odd */ }
x&1を使用する方が「より高速」または「より効率的」であると述べた上で、数人の人が私の答えを批判しました。私はこれが事実であるとは思わない。
好奇心から、2つの簡単なテストケースプログラムを作成しました。
/* modulo.c */
#include <stdio.h>
int main(void)
{
int x;
for (x = 0; x < 10; x++)
if (x % 2)
printf("%d is odd\n", x);
return 0;
}
/* and.c */
#include <stdio.h>
int main(void)
{
int x;
for (x = 0; x < 10; x++)
if (x & 1)
printf("%d is odd\n", x);
return 0;
}
次に、マシンの1つでgcc 4.1.3を使用してこれらを5回コンパイルしました。
(gcc -Sを使用して)各コンパイルのアセンブリ出力を調べたところ、それぞれの場合で、and.cとmodulo.cの出力は同じでした(両方ともandl $ 1、%eax命令を使用しました)。これは「新しい」機能ではないかと思いますが、古いバージョンに遡ると思われます。また、商用(オープンソース)の(過去20年間に作成された)非難解なコンパイラーがそのような最適化を欠いていることも疑います。他のコンパイラでテストしますが、現時点では利用できません。
他の誰かが他のコンパイラやプラットフォームターゲットをテストしたいと思っていて、異なる結果が得られた場合、私は知りたいと非常に興味があります。
最後に、モジュロバージョンは、符号付き整数の実装の表現に関係なく、整数が正、負、またはゼロのいずれであっても機能することが規格によって保証されています。ビット単位のバージョンではありません。はい、私は2の補数がいくぶん遍在していることを理解していますので、これは実際には問題ではありません。
君たちは効率が良すぎる あなたが本当に欲しいのは:
public boolean isOdd(int num) {
int i = 0;
boolean odd = false;
while (i != num) {
odd = !odd;
i = i + 1;
}
return odd;
}
について繰り返しisEven
ます。
もちろん、それは負の数に対しては機能しません。しかし、輝きには犠牲が伴います...
ビット演算を使用します。
if((x & 1) == 0)
printf("EVEN!\n");
else
printf("ODD!\n");
これは、除算または係数を使用するよりも高速です。
[冗談モード= "オン"]
public enum Evenness
{
Unknown = 0,
Even = 1,
Odd = 2
}
public static Evenness AnalyzeEvenness(object o)
{
if (o == null)
return Evenness.Unknown;
string foo = o.ToString();
if (String.IsNullOrEmpty(foo))
return Evenness.Unknown;
char bar = foo[foo.Length - 1];
switch (bar)
{
case '0':
case '2':
case '4':
case '6':
case '8':
return Evenness.Even;
case '1':
case '3':
case '5':
case '7':
case '9':
return Evenness.Odd;
default:
return Evenness.Unknown;
}
}
[冗談モード= "オフ"]
編集:enumに紛らわしい値を追加しました。
ffpfへの対応 -私は数年前に同僚とまったく同じ議論をしましたが、答えは「いいえ」で、負の数では機能しません。
C規格では、負の数は3つの方法で表すことができると規定されています。
このようにチェックする:
isEven = (x & 1);
2の補数と符号と大きさの表現では機能しますが、1の補数では機能しません。
しかし、私は以下がすべての場合にうまくいくと信じています:
isEven = (x & 1) ^ ((-1 & 1) | ((x < 0) ? 0 : 1)));
テキストボックスが私の小なり文字の後にすべてを食べていたことを指摘してくれたffpfに感謝します。
いいのは:
/*forward declaration, C compiles in one pass*/
bool isOdd(unsigned int n);
bool isEven(unsigned int n)
{
if (n == 0)
return true ; // I know 0 is even
else
return isOdd(n-1) ; // n is even if n-1 is odd
}
bool isOdd(unsigned int n)
{
if (n == 0)
return false ;
else
return isEven(n-1) ; // n is odd if n-1 is even
}
このメソッドは、2つの関数を含む末尾再帰を使用することに注意してください。コンパイラがSchemeコンパイラのように末尾再帰をサポートしている場合は、効率的に実装できます(while / untilのようなループに変わります)。この場合、スタックはオーバーフローしないはずです。
2で割ったときの余りが0の場合、数値は偶数です。2で割ったときの余りが1の場合、数値は奇数です。
// Java
public static boolean isOdd(int num){
return num % 2 != 0;
}
/* C */
int isOdd(int num){
return num % 2;
}
メソッドは素晴らしいです!
私はそれを2で割るだけだと思います。残りが0の場合は偶数で、それ以外の場合は奇数です。
係数(%)を使用すると、これが簡単になります。
例えば。4%2 = 0したがって4は偶数5%2 = 1したがって5は奇数
問題のもう1つの解決策
(子供は投票できます)
bool isEven(unsigned int x)
{
unsigned int half1 = 0, half2 = 0;
while (x)
{
if (x) { half1++; x--; }
if (x) { half2++; x--; }
}
return half1 == half2;
}
私は整数のパリティー(奇数の場合は1、奇数の場合は0)のテーブルを作成します(そのため、ルックアップを行うことができます:D)。しかし、gccでは、そのようなサイズの配列を作成できません。
typedef unsigned int uint;
char parity_uint [UINT_MAX];
char parity_sint_shifted [((uint) INT_MAX) + ((uint) abs (INT_MIN))];
char* parity_sint = parity_sint_shifted - INT_MIN;
void build_parity_tables () {
char parity = 0;
unsigned int ui;
for (ui = 1; ui <= UINT_MAX; ++ui) {
parity_uint [ui - 1] = parity;
parity = !parity;
}
parity = 0;
int si;
for (si = 1; si <= INT_MAX; ++si) {
parity_sint [si - 1] = parity;
parity = !parity;
}
parity = 1;
for (si = -1; si >= INT_MIN; --si) {
parity_sint [si] = parity;
parity = !parity;
}
}
char uparity (unsigned int n) {
if (n == 0) {
return 0;
}
return parity_uint [n - 1];
}
char sparity (int n) {
if (n == 0) {
return 0;
}
if (n < 0) {
++n;
}
return parity_sint [n - 1];
}
代わりに、偶数と奇数の数学的定義に代わりましょう。
整数nは、n = 2kのような整数kが存在する場合でも同じです。
n = 2k + 1であるような整数kが存在する場合、整数nは奇数です。
そのコードは次のとおりです。
char even (int n) {
int k;
for (k = INT_MIN; k <= INT_MAX; ++k) {
if (n == 2 * k) {
return 1;
}
}
return 0;
}
char odd (int n) {
int k;
for (k = INT_MIN; k <= INT_MAX; ++k) {
if (n == 2 * k + 1) {
return 1;
}
}
return 0;
}
Cの整数int
が、特定のCコンパイルでの可能な値を示すとしましょう。(C整数は整数のサブセットであることに注意してください。)
ここで、C整数の特定のnに対して、対応する整数kがC整数内に存在しない可能性があることを心配するかもしれません。しかし、少し証明すれば、すべての整数nに対して| n |であることを示すことができます。<= | 2n | (*)、| n | 「nが正の場合はn、それ以外の場合は-n」です。言い換えると、整数のすべてのnについて、次の少なくとも1つが当てはまります(実際にはケース(1および2)またはケース(3および4)ですが、ここでは証明しません)。
ケース1:n <= 2n。
ケース2:-n <= -2n。
ケース3:-n <= 2n。
ケース4:n <= -2n。
ここで2k = nを取ります。(nが偶数の場合、このようなakは存在しますが、ここでは証明しません。nが偶数でない場合、ループインeven
はいずれにしても早く戻ることができないため、問題ありません。)しかし、これは、n <n (*)による0ではなく、すべてのmについて、整数2m = zのzは、mが0でない場合、zがmに等しくないことを意味します。nが0の場合、2 * 0 = 0したがって、0は完了です(n = 0の場合、nは関数のC整数であるeven
ため、0はC整数です。したがって、k = 0はC整数です)。したがって、nが偶数の場合、C整数のそのようなakはC整数のnに対して存在します。
同様の議論は、nが奇数の場合、n = 2k + 1のようなC整数にkが存在することを示しています。
したがって、ここeven
でodd
紹介する関数は、すべてのC整数に対して適切に機能します。
i % 2
はるかに小さく、おそらくより効率的です。
%2
はすべての整数に対して機能します。
// C#
bool isEven = ((i % 2) == 0);
typedef
か、#define
または何か。
これがJavaの答えです:
public static boolean isEven (Integer Number) {
Pattern number = Pattern.compile("^.*?(?:[02]|8|(?:6|4))$");
String num = Number.toString(Number);
Boolean numbr = new Boolean(number.matcher(num).matches());
return numbr.booleanValue();
}
これを試して: return (((a>>1)<<1) == a)
例:
a = 10101011
-----------------
a>>1 --> 01010101
a<<1 --> 10101010
b = 10011100
-----------------
b>>1 --> 01001110
b<<1 --> 10011100
このかなり面白い議論を読んで、私はメインループ内で奇数と偶数をテストする実際の時間に敏感な関数があることを思い出しました。これは整数のべき関数であり、次のようにStackOverflowの他の場所に投稿されています。ベンチマークは驚くべきものでした。少なくともこの実際の関数では、モジュロはより遅く、大幅に遅くなります。勝者は、大差で、moduloの時間の67%を必要とし、or(|)アプローチであり、このページの他の場所にはありません。
static dbl IntPow(dbl st0, int x) {
UINT OrMask = UINT_MAX -1;
dbl st1=1.0;
if(0==x) return (dbl)1.0;
while(1 != x) {
if (UINT_MAX == (x|OrMask)) { // if LSB is 1...
//if(x & 1) {
//if(x % 2) {
st1 *= st0;
}
x = x >> 1; // shift x right 1 bit...
st0 *= st0;
}
return st1 * st0;
}
3億ループの場合、ベンチマークのタイミングは次のとおりです。
3.962 そしてマスクアプローチ
4.851&アプローチ
5.850%アプローチ
理論、またはアセンブリ言語のリストがこれらのような議論を解決することを考える人にとって、これは注意すべき物語です。天と地、ホレイショには、あなたの哲学で夢に見た以上のものが存在します。
unsigned x
をお勧めします。理由は不明で、タイプも異なります。テストを使用して書き直すのに十分なほど単純です。x = x >> 1;
x < 0
x
OrMask
while(x)
% 2
bitwiseを使用してケースをコンパイルするのに十分スマートである必要があるため、これをベンチマークに使用したコンパイラは何でしょうか&
。私はこれをテストしましたが、結果はまったく同じです(VS2015、x86とx64の両方のすべての最適化を含むリリースビルド)。受け入れられた回答は、GCCについても述べています(2008年に作成)。
or
方が、and
プラットフォームやコンパイラーではありそうもないよりも速いという前提があることです。そのような奇妙なプラットフォームとコンパイラの組み合わせがあったとしても(そして、ベンチマークを実行するために使用されるコードもコードも投稿していない場合)、同じように動作する他のコンパイラに依存することは、最適化策としては不十分です。したがって、私が書いたように、これがどのプラットフォーム/コンパイラでテストされたのかと思います。正確に測定されなかったことがほぼ確実だからです。
これは彼の回答に関する@RocketRoyとの議論のフォローアップですが、これらの結果を比較したい人にとっては役立つかもしれません。
tl; dr私が見てきたことから、Royのアプローチ((0xFFFFFFFF == (x | 0xFFFFFFFE)
)はアプローチx & 1
として完全に最適化されていませんmod
が、実際には、実行時間はすべてのケースで等しくなるはずです。
そこで、まず、コンパイラエクスプローラを使用して、コンパイルされた出力を比較しました。
テストされた機能:
int isOdd_mod(unsigned x) {
return (x % 2);
}
int isOdd_and(unsigned x) {
return (x & 1);
}
int isOdd_or(unsigned x) {
return (0xFFFFFFFF == (x | 0xFFFFFFFE));
}
CLang 3.9.0と-O3:
isOdd_mod(unsigned int): # @isOdd_mod(unsigned int)
and edi, 1
mov eax, edi
ret
isOdd_and(unsigned int): # @isOdd_and(unsigned int)
and edi, 1
mov eax, edi
ret
isOdd_or(unsigned int): # @isOdd_or(unsigned int)
and edi, 1
mov eax, edi
ret
-O3を使用したGCC 6.2:
isOdd_mod(unsigned int):
mov eax, edi
and eax, 1
ret
isOdd_and(unsigned int):
mov eax, edi
and eax, 1
ret
isOdd_or(unsigned int):
or edi, -2
xor eax, eax
cmp edi, -1
sete al
ret
CLangに帽子をかぶると、3つのケースすべてが機能的に等しいことがわかりました。ただし、RoyのアプローチはGCCでは最適化されていないため、YMMVです。
Visual Studioと同様です。これらの3つの機能について逆アセンブリリリースx64(VS2015)を調べると、比較部分が「mod」と「and」の場合は等しく、Royの「or」の場合は少し大きいことがわかりました。
// x % 2
test bl,1
je (some address)
// x & 1
test bl,1
je (some address)
// Roy's bitwise or
mov eax,ebx
or eax,0FFFFFFFEh
cmp eax,0FFFFFFFFh
jne (some address)
ただし、これらの3つのオプション(プレーンmod、ビットごと、またはビットごと)を比較するための実際のベンチマークを実行した後、結果は完全に同じでした(Visual Studio 2005 x86 / x64、リリースビルド、デバッガーは接続されていません)。
リリースアセンブリはとのケースのtest
指示を使用しますがand
、mod
ロイのケースはcmp eax,0FFFFFFFFh
アプローチを使用しますが、展開が大きく最適化されているため、実際に違いはありません。
20回実行した後の結果(i7 3610QM、Windows 10電源プランを高パフォーマンスに設定):
[テスト:プレーンmod 2]平均時間:689.29 ms(相対差分:+ 0.000%) [テスト:ビット単位または]平均時間:689.63ミリ秒(相対差分:+ 0.048%) [テスト:ビット単位および]平均時間:687.80 ms(相対差分:-0.217%)
これらのオプションの差は0.3%未満なので、すべてのケースでアセンブリが等しいことは明らかです。
誰かが試したい場合のコードは次のとおりです。ただし、Windowsでのみテストしたことに注意してください(定義の#if LINUX
条件を確認し、get_time
必要に応じて、この回答から取得して実装しています)。
#include <stdio.h>
#if LINUX
#include <sys/time.h>
#include <sys/resource.h>
double get_time()
{
struct timeval t;
struct timezone tzp;
gettimeofday(&t, &tzp);
return t.tv_sec + t.tv_usec*1e-6;
}
#else
#include <windows.h>
double get_time()
{
LARGE_INTEGER t, f;
QueryPerformanceCounter(&t);
QueryPerformanceFrequency(&f);
return (double)t.QuadPart / (double)f.QuadPart * 1000.0;
}
#endif
#define NUM_ITERATIONS (1000 * 1000 * 1000)
// using a macro to avoid function call overhead
#define Benchmark(accumulator, name, operation) { \
double startTime = get_time(); \
double dummySum = 0.0, elapsed; \
int x; \
for (x = 0; x < NUM_ITERATIONS; x++) { \
if (operation) dummySum += x; \
} \
elapsed = get_time() - startTime; \
accumulator += elapsed; \
if (dummySum > 2000) \
printf("[Test: %-12s] %0.2f ms\r\n", name, elapsed); \
}
void DumpAverage(char *test, double totalTime, double reference)
{
printf("[Test: %-12s] AVERAGE TIME: %0.2f ms (Relative diff.: %+6.3f%%)\r\n",
test, totalTime, (totalTime - reference) / reference * 100.0);
}
int main(void)
{
int repeats = 20;
double runningTimes[3] = { 0 };
int k;
for (k = 0; k < repeats; k++) {
printf("Run %d of %d...\r\n", k + 1, repeats);
Benchmark(runningTimes[0], "Plain mod 2", (x % 2));
Benchmark(runningTimes[1], "Bitwise or", (0xFFFFFFFF == (x | 0xFFFFFFFE)));
Benchmark(runningTimes[2], "Bitwise and", (x & 1));
}
{
double reference = runningTimes[0] / repeats;
printf("\r\n");
DumpAverage("Plain mod 2", runningTimes[0] / repeats, reference);
DumpAverage("Bitwise or", runningTimes[1] / repeats, reference);
DumpAverage("Bitwise and", runningTimes[2] / repeats, reference);
}
getchar();
return 0;
}
私はこれが構文糖であり、.netにのみ適用できることを知っていますが、拡張メソッドについてはどうですか...
public static class RudiGroblerExtensions
{
public static bool IsOdd(this int i)
{
return ((i % 2) != 0);
}
}
今、あなたは次のことができます
int i = 5;
if (i.IsOdd())
{
// Do something...
}
一部の人々が投稿したように、これを行うには多くの方法があります。このウェブサイトによると、最速の方法はモジュラス演算子です:
if (x % 2 == 0)
total += 1; //even number
else
total -= 1; //odd number
ただし、ここでは、上記の一般的なモジュラス演算よりも実行速度が遅い、作者によってベンチマークされた他のいくつかのコードを示します。
if ((x & 1) == 0)
total += 1; //even number
else
total -= 1; //odd number
System.Math.DivRem((long)x, (long)2, out outvalue);
if ( outvalue == 0)
total += 1; //even number
else
total -= 1; //odd number
if (((x / 2) * 2) == x)
total += 1; //even number
else
total -= 1; //odd number
if (((x >> 1) << 1) == x)
total += 1; //even number
else
total -= 1; //odd number
while (index > 1)
index -= 2;
if (index == 0)
total += 1; //even number
else
total -= 1; //odd number
tempstr = x.ToString();
index = tempstr.Length - 1;
//this assumes base 10
if (tempstr[index] == '0' || tempstr[index] == '2' || tempstr[index] == '4' || tempstr[index] == '6' || tempstr[index] == '8')
total += 1; //even number
else
total -= 1; //odd number
Math.System.DivRemメソッドを知っている人は何人か、またはなぜそれを使用するのでしょうか?
私たちの研究中にブール代数をあまり実行しなかった私たちのためにビットごとの演算子法についてさらに詳しく説明するために、ここに説明があります。おそらくOPにはあまり役に立ちませんが、NUMBER&1が機能する理由を明確にしたいと思いました。
上で誰かが答えたように、負の数が表現される方法はこの方法が機能しなくなる可能性があることに注意してください。実際、各言語は負のオペランドの扱い方が異なる場合があるため、モジュロ演算子法も破ることができます。
ただし、NUMBERが常に正であることがわかっている場合、これはうまく機能します。
上記のTooonyが指摘したように、重要なのはバイナリ(および拒否)の最後の桁のみです。
ブール論理ANDゲートは、1が返されるためには両方の入力が1(または高電圧)でなければならないことを指示します。
1&0 = 0。
0&1 = 0。
0&0 = 0。
1&1 = 1。
バイナリとして数値を表す場合(ここでは8ビット表現を使用しました)、奇数の最後には1があり、偶数には0があります。
例えば:
1 = 00000001
2 = 00000010
3 = 00000011
4 = 00000100
任意の数値を取り、ビットごとのAND(Javaでは&)を使用すると、1で00000001、= 1のいずれかが返され、数値が奇数であることを意味します。または00000000 = 0は、数値が偶数であることを意味します。
例えば
変ですか?
1&1 =
00000001&
00000001 =
00000001 <—奇数
2&1 =
00000010&
00000001 =
00000000 <—偶数
54&1 =
00000001&
00110110 =
00000000 <—偶数
これがこれが機能する理由です:
if(number & 1){
//Number is odd
} else {
//Number is even
}
これが冗長な場合は申し訳ありません。
ゼロパリティ| ゼロhttp://tinyurl.com/oexhr3k
Pythonコードシーケンス。
# defining function for number parity check
def parity(number):
"""Parity check function"""
# if number is 0 (zero) return 'Zero neither ODD nor EVEN',
# otherwise number&1, checking last bit, if 0, then EVEN,
# if 1, then ODD.
return (number == 0 and 'Zero neither ODD nor EVEN') \
or (number&1 and 'ODD' or 'EVEN')
# cycle trough numbers from 0 to 13
for number in range(0, 14):
print "{0:>4} : {0:08b} : {1:}".format(number, parity(number))
出力:
0 : 00000000 : Zero neither ODD nor EVEN
1 : 00000001 : ODD
2 : 00000010 : EVEN
3 : 00000011 : ODD
4 : 00000100 : EVEN
5 : 00000101 : ODD
6 : 00000110 : EVEN
7 : 00000111 : ODD
8 : 00001000 : EVEN
9 : 00001001 : ODD
10 : 00001010 : EVEN
11 : 00001011 : ODD
12 : 00001100 : EVEN
13 : 00001101 : ODD
議論のために...
あなたはそれが偶数であるか奇数であるかを確認するために与えられた数の最後の数字を見る必要があるだけです。署名済み、署名なし、ポジティブ、ネガティブ-これに関してはすべて同じです。だからこれはすべてのラウンドで動作するはずです:-
void tellMeIfItIsAnOddNumberPlease(int iToTest){
int iLastDigit;
iLastDigit = iToTest - (iToTest / 10 * 10);
if (iLastDigit % 2 == 0){
printf("The number %d is even!\n", iToTest);
} else {
printf("The number %d is odd!\n", iToTest);
}
}
ここで重要なのはコードの3行目です。除算演算子は整数除算を実行するため、結果の小数部分が欠落しています。したがって、たとえば222/10は結果として22になります。次に、10を再度掛けると、220になります。元の222からそれを引くと、最終的に2になります。これは、元の番号の最後の数字と同じ数です。;-)括弧は、計算が行われた順序を思い出させるためにあります。最初に除算と乗算を行ってから、元の数値から結果を減算します。除算よりも除算や乗算の方が優先度が高いため、省略してもかまいませんが、これにより「読みやすく」なるコードが得られます。
必要に応じて、すべてを完全に読み取り不可能にすることができます。それは現代のコンパイラーにはまったく違いがありません:-
printf("%d%s\n",iToTest,0==(iToTest-iToTest/10*10)%2?" is even":" is odd");
しかし、それはコードを将来的に維持することをより困難にするでしょう。奇数のテキストを「等しくない」に変更するとします。次に、後で他の誰かがあなたが行った変更を見つけて、svn diffまたは同様のものを実行したいと考えています...
移植性については心配せず、速度について心配している場合は、最下位ビットを確認できます。そのビットが1に設定されている場合は奇数、0の場合は偶数です。Intelのx86アーキテクチャのようなリトルエンディアンシステムでは、次のようになります。-
if (iToTest & 1) {
// Even
} else {
// Odd
}
あなたが効率的になりたい場合は、使用のビット演算子(x & 1
)、しかし、あなたは読めるの使用法2(になりたい場合x % 2
)
%
。読みやすくしたい場合は、を使用してください%
。うーん、ここに柄が見えます。
偶数または奇数のチェックは簡単な作業です。
2で割り切れる数は偶数であり、それ以外は奇数であることがわかっています。
任意の数の可分性をチェックするだけでよく、可算性をチェックするために%
演算子を使用します
ifを使用して奇数をチェックする
if(num%2 ==0)
{
printf("Even");
}
else
{
printf("Odd");
}
条件付き/三項演算子の使用
(num%2 ==0) printf("Even") : printf("Odd");
条件演算子を使用して偶数または奇数をチェックするCプログラム。
ビット演算子の使用
if(num & 1)
{
printf("Odd");
}
else
{
printf("Even");
}
!(i%2) / i%2 == 0
int isOdd(int n)
{
return n & 1;
}
1の場合、コードは整数の最後のビットをチェックしますバイナリで
Binary : Decimal
-------------------
0000 = 0
0001 = 1
0010 = 2
0011 = 3
0100 = 4
0101 = 5
0110 = 6
0111 = 7
1000 = 8
1001 = 9
and so on...
注意してください右端のビットは常に1である奇数の番号。
&ビット単位のAND演算子をチェックし、私たちの右端のビットのリターンラインは、それが1だ場合
nを1と比較すると0001
、2進数であることを意味します(ゼロの数は関係ありません)。
次に、整数nがあると想像してみましょう、サイズが1バイトのとします。
それは、8ビット/ 8進数で表されます。
int nが7であり、それを1と比較すると、
7 (1-byte int)| 0 0 0 0 0 1 1 1
&
1 (1-byte int)| 0 0 0 0 0 0 0 1
********************************************
Result | F F F F F F F T
これはFが虚偽との略T真のために。
これは、比較し、彼らは両方とも真ならのみ右端のビットを。つまり、自動的
7 & 1
にT rueです。
2が表すものに変更n & 1
するだけですn & 2
0010
バイナリにしてそうで。
ビット演算の初心者の場合は、16進表記を使用することをお勧めします
return n & 1;
>> return n & 0x01;
。