Làm cách nào để kiểm tra xem một số nguyên là chẵn hay lẻ? [đóng cửa]


193

Làm cách nào để kiểm tra xem một số đã cho là chẵn hay lẻ trong C?


5
Phiên bản sử dụng bitwise và (&) hiệu quả hơn nhiều so với phiên bản modulo (%). Bạn nên thay đổi câu bạn chọn là câu trả lời đúng.
Stefan Rusek

6
Không có khả năng quan trọng - đối số là một hằng số. Dễ dàng cho trình tối ưu hóa
MSalters

2
Yếu tố dễ đọc vào đây là tốt.
Brian G

2
Trong các ứng dụng nhúng (thế giới nơi tôi dành phần lớn thời gian lập trình), một số bộ xử lý có các đơn vị số học rất nguyên thủy và không thể thực hiện các thao tác phân chia / mô đun một cách dễ dàng. Vì lý do này, tôi thường sử dụng phương pháp bitwise và thay vào đó. Tuy nhiên, trên CPU của máy tính để bàn hiện đại, điều này sẽ không xảy ra.
bta

3
Tôi chưa bao giờ thấy hoạt động mô đun để dễ hiểu hơn. Khi tôi lần đầu tiên cần xác định chẵn hay lẻ, mặt nạ bitwise là điều đầu tiên xuất hiện trong đầu. Điều đó hơi tự nhiên, vì cách chúng ta có xu hướng làm điều này bằng tay là nhìn vào chữ số có nghĩa ít nhất để xem nó có trong {0 2 4 6 8} hay {1 3 5 7 9}. Điều đó chuyển trực tiếp sang việc nhìn vào bit có ý nghĩa nhỏ nhất để xem đó là 0 hay 1.
P Daddy

Câu trả lời:


449

Sử dụng toán tử modulo (%) để kiểm tra xem có phần dư không khi chia cho 2:

if (x % 2) { /* x is odd */ }

Một số người đã chỉ trích câu trả lời của tôi ở trên nói rằng sử dụng x & 1 là "nhanh hơn" hoặc "hiệu quả hơn". Tôi không tin đây là trường hợp.

Vì tò mò, tôi đã tạo ra hai chương trình thử nghiệm tầm thường:

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

Sau đó tôi đã biên dịch những thứ này với gcc 4.1.3 trên một trong các máy của tôi 5 lần khác nhau:

  • Không có cờ tối ưu hóa.
  • Với -O
  • Với -Os
  • Với -O2
  • Với -O3

Tôi đã kiểm tra đầu ra lắp ráp của mỗi trình biên dịch (sử dụng gcc -S) và thấy rằng trong mỗi trường hợp, đầu ra cho and.c và modulo.c giống hệt nhau (cả hai đều sử dụng lệnh andl $ 1,% eax). Tôi nghi ngờ đây là một tính năng "mới" và tôi nghi ngờ nó có từ phiên bản cổ. Tôi cũng nghi ngờ bất kỳ trình biên dịch không phức tạp hiện đại (được thực hiện trong 20 năm qua), thương mại hoặc nguồn mở, thiếu tối ưu hóa như vậy. Tôi sẽ thử nghiệm trên các trình biên dịch khác, nhưng hiện tại tôi không có sẵn bất kỳ trình biên dịch nào.

Nếu bất cứ ai khác quan tâm đến việc kiểm tra các trình biên dịch và / hoặc các mục tiêu nền tảng khác và nhận được một kết quả khác, tôi rất muốn biết.

Cuối cùng, phiên bản modulo được đảm bảo bởi tiêu chuẩn để hoạt động cho dù số nguyên là dương, âm hay bằng 0, bất kể việc biểu diễn các số nguyên đã ký. Phiên bản bitwise và phiên bản thì không. Vâng, tôi nhận ra bổ sung của hai là hơi phổ biến, vì vậy đây không thực sự là một vấn đề.


11
Câu hỏi đặc biệt hỏi làm thế nào để làm điều đó trong C vì vậy tôi đã trả lời nó bằng C, mặc dù đã đề cập đến việc họ không thể tìm ra cách thực hiện nó trong Java. Tôi không khẳng định hoặc ngụ ý đây là câu trả lời Java, tôi không biết Java. Tôi nghĩ rằng tôi vừa có downvote đầu tiên của tôi và bối rối là tại sao. Ồ tốt
Chris Young

33
Tôi muốn nói, nếu (x% 2! = 0) {/ * x là số lẻ * /}, nhưng ai biết được. Cũng không biết java.
eugensk

9
Nó nhận được rất nhiều sự ủng hộ để phân biệt nó với các nhà điều hành bitwise, mà không phải bỏ nghiệp của chúng ta bỏ phiếu cho họ.
wnoise

13
Tôi đồng ý với tất cả mọi thứ, ngoại trừ một điều: Tôi thích giữ các số nguyên và giá trị chân lý tách biệt, theo khái niệm, vì vậy tôi thích viết "if (x% 2 == 1)". Nó giống với trình biên dịch, nhưng có lẽ rõ ràng hơn với con người. Ngoài ra, bạn có thể sử dụng cùng một mã trong các ngôn ngữ không diễn giải khác không là đúng.
Thomas Padron-McCarthy

46
Điểm chuẩn của tôi? Điểm chuẩn nào? Tôi đã không làm bất kỳ điểm chuẩn. Tôi đã kiểm tra ngôn ngữ lắp ráp được tạo ra. Điều này hoàn toàn không có gì để làm với printf.
Chris Young

207

Các bạn đang waaaaaaaay quá hiệu quả. Những gì bạn thực sự muốn là:

public boolean isOdd(int num) {
  int i = 0;
  boolean odd = false;

  while (i != num) {
    odd = !odd;
    i = i + 1;
  }

  return odd;
}

Lặp lại cho isEven.

Tất nhiên, điều đó không làm việc cho các số âm. Nhưng với sự sáng chói đến sự hy sinh ...


17
Nếu bạn đã ném một ngoại lệ đối số trên các giá trị âm và lưu ý trong tài liệu rằng hàm này là O (N), thì tôi sẽ ổn với điều này.
Jeffrey L Whitledge

7
Phiên bản doanh nghiệp sẽ phải sử dụng XML. Tất nhiên ngày nay bạn sẽ có một dịch vụ web mà bạn có thể truy vấn
Martin Beckett

58
Bạn nên tối ưu hóa điều này với một bảng tra cứu.
Weeble

1
Tôi là một tu sĩ như vậy, đã phải +1 đại diện của bạn vào 999 thiên niên kỷ mới
Eran Medan

7
Thật là tuyệt vời! Sếp của tôi nói với tôi rằng chúng tôi có một khách hàng rất tức giận vì anh ta cảm thấy Giấy phép Doanh nghiệp của mình không cung cấp gì nhiều hơn Giấy phép Tiêu chuẩn. Bây giờ chúng tôi đã thêm chức năng này trong chương trình của mình và chỉ vì nó hoạt động chậm hơn, anh ấy nghĩ rằng phần mềm của anh ấy đang làm việc nhiều hơn !!!
Phil

97

Sử dụng số học bit:

if((x & 1) == 0)
    printf("EVEN!\n");
else
    printf("ODD!\n");

Điều này nhanh hơn so với sử dụng phép chia hoặc mô đun.


43
Tôi không nghĩ thật công bằng khi nói nó nhanh hơn việc sử dụng phép chia hoặc mô đun. Tiêu chuẩn C không nói gì về hiệu năng của các toán tử và bất kỳ trình biên dịch tử tế nào cũng sẽ tạo ra mã nhanh cho cả hai. Cá nhân tôi sẽ chọn thành ngữ truyền đạt ý định của mình và% có vẻ phù hợp hơn ở đây
Chris Young

21
Tôi thích (x & 1) tốt hơn, bởi vì nó kiểm tra xem số đó có giống như cách mọi người làm hay không: kiểm tra xem chữ số cuối là chẵn hay lẻ. Theo tôi nó truyền đạt ý định của nó nhiều hơn phương pháp modulo. (Không phải là vấn đề nhiều.)
Jeremy Ruten

2
Bạn nói đúng, tôi đoán đó là chủ quan. Mặc dù định nghĩa thông thường của "chẵn" là "số nguyên chia hết cho 2", chứ không phải "số nguyên kết thúc bằng 0, 2, 4, 6 hoặc 8". :-)
Chris Young

4
@TraumaPony - đối với ANSI tiêu chuẩn C và Java sớm, tùy thuộc vào hệ thống máy tính. Không xác định đại diện nào được sử dụng cho các số đã ký - lời khen 2, lời khen 1, mã màu xám, v.v. Nhưng mô-đun luôn là mô-đun
Aaron

9
Không hoạt động phổ biến cho các số âm. Xem Kiểm tra câu trả lời này để biết thêm chi tiết: stackoverflow.com/questions/160930/ trên để biết chi tiết.
Andrew Edgecombe

36

[Chế độ trò đùa = "bật"]

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

[Chế độ trò đùa = "tắt"]

EDIT: Đã thêm các giá trị khó hiểu vào enum.


2
Wow ... điều này đáng sợ hơn giải pháp của SCdF! Thanh danh! Không có upvote mặc dù ... không thể đề nghị này. Nhưng cảm ơn vì sự hài hước!
Wes P

1
Ưu điểm của phương pháp này là nó hoạt động với nhiều hơn chỉ là số. Ngoài ra, nếu bạn thay thế dòng này: char bar = foo [foo.Lipse - 1]; với điều này: double bar = Char.GetNumericValue (foo [foo.Lipse - 1]); Sau đó, nó sẽ làm việc với bất kỳ hệ thống số.
Jeffrey L Whitledge

5
báo cáo lỗi: 14,65 được báo cáo là số lẻ khi không xác định được.
TheSoftwareJedi

4
Phần mềm Jedi, đó là một "tính năng". ;)
Sklivvz

31
TheSoftwareJedi: 14,65 là một trong những số nguyên kỳ lạ nhất tôi từng thấy.
Bruce Alderman

16

Đáp lại ffpf - tôi đã có chính xác lập luận tương tự với một đồng nghiệp nhiều năm trước, và câu trả lời là không , nó không hoạt động với các số âm.

Tiêu chuẩn C quy định rằng các số âm có thể được biểu diễn theo 3 cách:

  • Bổ sung 2
  • Bổ sung 1
  • dấu hiệu và cường độ

Kiểm tra như thế này:

isEven = (x & 1);

sẽ hoạt động cho phần bù của 2 và biểu thị cường độ, nhưng không cho phần bù của 1.

Tuy nhiên, tôi tin rằng những điều sau đây sẽ hoạt động cho tất cả các trường hợp:

isEven = (x & 1) ^ ((-1 & 1) | ((x < 0) ? 0 : 1)));

Cảm ơn ffpf đã chỉ ra rằng hộp văn bản đã ăn mọi thứ sau khi tôi ít hơn nhân vật!


Tôi nghĩ rằng ví dụ mã thứ hai của bạn thiếu một số văn bản.
Jeff Yates

3
Hãy khen những con số đó!
thejh

14

Một điều tốt đẹp là:

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

Lưu ý rằng phương pháp này sử dụng đệ quy đuôi liên quan đến hai chức năng. Nó có thể được thực hiện một cách hiệu quả (biến thành một vòng / cho đến khi loại vòng lặp) nếu trình biên dịch của bạn hỗ trợ đệ quy đuôi như trình biên dịch Scheme. Trong trường hợp này, ngăn xếp không nên tràn!


1
Điều này không xử lý tốt isOdd (0).
Steve McLeod

1
Tôi nghĩ rằng bạn đã có một vòng lặp vô hạn (với đệ quy đuôi) hoặc tràn ngăn xếp (không có đệ quy đuôi) cho isOdd () với bất kỳ giá trị chẵn hoặc isEven () với bất kỳ giá trị lẻ nào. Nó chỉ chấm dứt với sự thật. Đó là vấn đề tạm dừng một lần nữa.
Jeffrey L Whitledge

7
Ồ, chắc chắn, sửa nó mà không có bình luận, và làm cho tôi trông như một thằng ngốc. Tốt rồi.
Jeffrey L Whitledge

1
Bây giờ, bạn đã có một lỗi biên dịch: trong isEven không phải tất cả các đường dẫn mã đều trả về một giá trị. Không, tôi thực sự đã không thử mã này, đó là trình biên dịch trong đầu tôi đang phàn nàn.
Jeffrey L Whitledge

5
biên dịch lỗi: không phải tất cả các đường dẫn đều trả về giá trị ghét bạn khi bắn phá bạn bằng các nhận xét lỗi về mã mẫu của bạn, nhưng điều gì xảy ra khi bạn gọi làEven (5)
Kevin

11

Một số chẵn nếu, khi chia cho hai, phần còn lại là 0. Một số là số lẻ nếu, khi chia cho 2, phần còn lại là 1.

// Java
public static boolean isOdd(int num){
    return num % 2 != 0;
}

/* C */
int isOdd(int num){
    return num % 2;
}

Phương pháp rất hay!


Phương thức Java của bạn bị hỏng vì num% 2 == -1 cho các số lẻ âm.
WMR

Có phải đó là lý do tại sao bạn đánh giá thấp tôi?
jjnguy

3
Tôi đã đánh giá thấp nó bởi vì hàm của bạn trong C cần nhiều ký tự để nhập hơn những gì nó làm. IE num% I là 7 ký tự bao gồm khoảng trắng IsOdd (I) là 8 ký tự. Tại sao bạn sẽ tạo một chức năng dài hơn chỉ thực hiện thao tác?
Kevin

13
@Kevin theo ý kiến ​​của tôi mã không được đo bằng ký tự mà thay vào đó là thời gian bạn cần để viết nó, bao gồm cả thời gian suy nghĩ + gỡ lỗi. num% 2 mất nhiều hơn một phần nghìn giây để nghĩ về isOdd. bây giờ thêm các số trên toàn cầu và bạn mất một năm tập thể. cũng có thể kiểm tra isOdd, và được xác minh và cuối cùng được chứng nhận không có lỗi (ví dụ: xử lý các số âm) trong khi num% 2 - một số nhà phát triển sẽ luôn nghi ngờ và đi thử nghiệm. mã tốt là mã bạn không viết, chỉ sử dụng lại ... chỉ 2 xu của tôi.
Eran Medan

2
@EranMedan, logic tương tự sẽ được áp dụng để thay thế i ++ bằng IncrementByOne (i) và đó cũng là một ý tưởng tồi. Nếu một nhà phát triển nghi ngờ về những gì num% 2 làm, tôi không muốn anh ta hoặc cô ta ở bất cứ đâu gần mã của tôi.
Kevin


7

Tôi muốn nói chỉ cần chia nó cho 2 và nếu có 0 phần còn lại, nó thậm chí, nếu không nó là số lẻ.

Sử dụng mô-đun (%) làm cho điều này dễ dàng.

ví dụ. 4% 2 = 0 do đó 4 thậm chí 5% 2 = 1 do đó 5 là số lẻ


6

Thêm một giải pháp cho vấn đề
(trẻ em được hoan nghênh bầu chọn)

bool isEven(unsigned int x)
{
  unsigned int half1 = 0, half2 = 0;
  while (x)
  {
     if (x) { half1++; x--; }
     if (x) { half2++; x--; }

  }
  return half1 == half2;
}

Không, bạn không phải là đứa trẻ mà tôi đã tính đến :)
eugensk

Tôi sẽ nâng cao điều này, nhưng nó hơi chậm với các số âm. :)
Chris Young

3
Tất cả các số đều tươi sáng và tích cực. Hay bạn có thành kiến ​​với một số? :))
eugensk

3
Trong máy tính, tất cả các số một lần âm, cuối cùng trở nên tích cực. Chúng tôi gọi đó là Rollover of Happiness (không áp dụng cho BIGNUMS, YMMY, không hợp lệ ở tất cả các tiểu bang).
Will Hartung

@WillHartung "tái đầu tư hạnh phúc" thật tuyệt! : D
thejh 30/03/13

6

Tôi sẽ xây dựng một bảng các số chẵn lẻ (0 nếu chẵn 1 nếu lẻ) của các số nguyên (để người ta có thể tra cứu: D), nhưng gcc sẽ không cho phép tôi tạo các mảng có kích thước như vậy:

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

Vì vậy, thay vào đó hãy sử dụng định nghĩa toán học của chẵn và lẻ.

Một số nguyên n thậm chí nếu tồn tại một số nguyên k sao cho n = 2k.

Một số nguyên n là số lẻ nếu tồn tại một số nguyên k sao cho n = 2k + 1.

Đây là mã cho 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;
}

Đặt số nguyên C biểu thị các giá trị có thể có của int trong một biên dịch C đã cho. (Lưu ý rằng số nguyên C là tập con của số nguyên.)

Bây giờ người ta có thể lo lắng rằng với một n đã cho trong các số nguyên C thì số nguyên k tương ứng có thể không tồn tại trong các số nguyên C. Nhưng với một ít bằng chứng, có thể chỉ ra rằng với mọi số nguyên n, | n | <= | 2n | (*), trong đó | n | là "n nếu n là dương và -n nếu không". Nói cách khác, với tất cả n trong số nguyên ít nhất một trong các lần giữ sau (chính xác là một trong hai trường hợp (1 và 2) hoặc trường hợp (3 và 4) trên thực tế nhưng tôi sẽ không chứng minh điều đó ở đây):

Trường hợp 1: n <= 2n.

Trường hợp 2: -n <= -2n.

Trường hợp 3: -n <= 2n.

Trường hợp 4: n <= -2n.

Bây giờ lấy 2k = n. (Như vậy không tồn tại nếu n chẵn, nhưng tôi sẽ không chứng minh điều đó ở đây. Nếu n thậm chí không phải là vòng lặp evenkhông thể quay lại sớm, vì vậy nó không thành vấn đề.) Nhưng điều này ngụ ý k <n nếu n không phải 0 bởi (*) và thực tế (một lần nữa không được chứng minh ở đây) rằng với mọi m, z trong các số nguyên 2m = z ngụ ý z không bằng m đã cho m không bằng 0. Trong trường hợp n là 0, 2 * 0 = 0 vì vậy 0 là chẵn, chúng ta đã hoàn thành (nếu n = 0 thì 0 nằm trong số nguyên C vì n nằm trong số nguyên C trong hàm even, do đó k = 0 nằm trong số nguyên C). Do đó ak trong số nguyên C tồn tại cho n trong số nguyên C nếu n chẵn.

Một đối số tương tự cho thấy rằng nếu n là số lẻ, tồn tại ak trong các số nguyên C sao cho n = 2k + 1.

Do đó, các hàm evenoddđược trình bày ở đây sẽ hoạt động đúng cho tất cả các số nguyên C.


1
Tôi không có ý xúc phạm, nhưng ý nghĩa của câu trả lời này là gì? i % 2nhỏ hơn nhiều và có thể hiệu quả hơn.
GManNickG

2
@GMan: Nhưng đây là cách quyết định hơn! Điều này sẽ làm việc chính xác phát hiện tất cả các trường hợp cạnh.
P Daddy

1
... VÀ (!!!) đúng rồi !!!
Thomas Eding

Tôi không thể biết bạn có đùa hay không. : X %2hoạt động cho tất cả các số nguyên.
GManNickG

1
+1: Tôi sẽ nói "Trả lời tốt", nhưng tôi nghĩ "Trả lời thú vị" là phù hợp hơn.
James Webster

5
// C#
bool isEven = ((i % 2) == 0);

2
Gì? Đó không phải là C #! Đó là C thuần túy! :-P
asterite

8
Tôi sẽ ném WinForm xung quanh nó để biến nó thành C # ...
Michael Petrotta

@mateusza: Thông thường khi bạn thấy "bool" trong một số hoa hoặc khác trong C, đó là một typedefhoặc #definehoặc một cái gì đó.
David Thornley

2
@mateusza @David Thornley Trong C99 bool là một tính năng tiêu chuẩn ( en.wikipedia.org/wiki/Stdbool.h )
fortran

1
Nói về dấu ngoặc đơn dư thừa ...
Thomas Eding

4

Đây là một câu trả lời trong 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();
}

4

Thử cái này: return (((a>>1)<<1) == a)

Thí dụ:

a     =  10101011
-----------------
a>>1 --> 01010101
a<<1 --> 10101010

b     =  10011100
-----------------
b>>1 --> 01001110
b<<1 --> 10011100

Bạn có thể giải thích điều này xin vui lòng? Tôi rất lạ lẫm với các nhà khai thác bitwise
Abdul

Chuyển sang phải và sau đó sang trái sẽ bằng không bit cuối cùng của bạn (cái phải nhất). Nếu số mới giống với số ban đầu, điều này có nghĩa là bit cuối cùng của số ban đầu là 0. Vì vậy, nó là số chẵn. Hãy xem câu trả lời cập nhật của tôi.
Kiril Aleksandrov

cảm ơn, tôi hiểu rồi
Abdul

Tôi không chắc cách tiếp cận nào nhanh hơn. Tôi đã không thử điểm chuẩn chúng.
Kiril Aleksandrov

Không phải điều này cũng không có bit đáng kể nhất của bạn? Một vấn đề với số nguyên không dấu trong một số ngôn ngữ và số nguyên âm trong hầu hết ...
Troyseph

4

Đọc cuộc thảo luận khá thú vị này, tôi nhớ rằng tôi có một chức năng nhạy cảm với thời gian trong thế giới thực, đã kiểm tra các số lẻ và chẵn trong vòng lặp chính. Đây là một hàm năng lượng nguyên, được đăng ở nơi khác trên StackOverflow, như sau. Các điểm chuẩn là khá ngạc nhiên. Ít nhất là trong chức năng trong thế giới thực này, modulo chậm hơn và đáng kể là như vậy. Người chiến thắng, với biên độ rộng, yêu cầu 67% thời gian của modul, là một cách tiếp cận hoặc (|) và không tìm thấy ở đâu trên trang này.

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

Đối với 300 triệu vòng lặp, thời gian chuẩn như sau.

3.962 cái | và mặt nạ tiếp cận

4.851 và cách tiếp cận

5,850 cách tiếp cận%

Đối với những người nghĩ về lý thuyết, hoặc một danh sách ngôn ngữ lắp ráp, giải quyết các đối số như thế này, đây sẽ là một câu chuyện cảnh báo. Có nhiều điều trên thiên đường và trái đất, Horatio, hơn là mơ ước trong triết lý của bạn.


1
Tốt hơn để sử dụng unsigned xnhư x = x >> 1;là hành vi được xác định thực hiện khi x < 0. Không rõ tại sao xOrMaskkhác nhau về loại. Đủ đơn giản để viết lại bằng cách sử dụng một while(x)bài kiểm tra.
chux - Tái lập Monica

2
Tôi tự hỏi trình biên dịch nào bạn đã sử dụng để điểm chuẩn này, vì hầu hết các trình biên dịch nên đủ thông minh để biên dịch % 2trường hợp bằng cách sử dụng bitwise &. Tôi mới thử nghiệm điều này và kết quả hoàn toàn giống nhau (VS2015, Bản dựng phát hành với tất cả các tối ưu hóa, cả x86 và x64). Câu trả lời được chấp nhận cũng nêu điều này cho GCC (viết năm 2008).
Lou

2
Vấn đề với bài đăng này là tiền đề rằng một bitwise orsẽ nhanh hơn bất kỳ andrất khó xảy ra, trên bất kỳ nền tảng / trình biên dịch nào. Ngay cả khi có một kết hợp nền tảng / trình biên dịch kỳ lạ như vậy (và bạn đã không đăng cả mã cũng không được sử dụng để thực hiện điểm chuẩn), tùy thuộc vào các trình biên dịch khác để hành xử tương tự sẽ là một đặt cược tối ưu hóa kém. Vì vậy, như tôi đã viết, tôi tự hỏi nền tảng / trình biên dịch này đã được thử nghiệm trên đó , bởi vì tôi gần như chắc chắn rằng nó không được đo chính xác.
Lou

2
Không gọi bạn là kẻ nói dối, chỉ tuyên bố với sự chắc chắn cao rằng bạn đã không đo lường chính xác. Không cần gọi tôi là tài xế xe tải, hãy đọc nhận xét ban đầu của tôi: Tôi đã thực hiện một điểm chuẩn và kết quả, như mong đợi, hoàn toàn giống nhau trong cả ba trường hợp (chắc chắn ~ 3 sigma, sau khi chạy mỗi bài kiểm tra 10 lần với giá 500.000 .000 lần lặp). Nếu bạn thực sự có một sự nghiệp lừng lẫy lâu dài, hãy lùi lại một bước và suy nghĩ xem những tuyên bố của bạn có ý nghĩa hay không, sau đó đăng mã thực tế được sử dụng để làm điểm chuẩn. Mặt khác, bài viết là những gì tôi tin rằng nó chỉ là một sai lầm trong đo lường.
Lou


4

Đây là phần tiếp theo cuộc thảo luận với @RocketRoy về câu trả lời của anh ấy , nhưng nó có thể hữu ích cho bất kỳ ai muốn so sánh các kết quả này.

tl; dr Từ những gì tôi đã thấy, cách tiếp cận của Roy ( (0xFFFFFFFF == (x | 0xFFFFFFFE)) không hoàn toàn được tối ưu hóa x & 1như modcách tiếp cận, nhưng trong thực tế, thời gian chạy sẽ trở nên bình đẳng trong mọi trường hợp.

Vì vậy, trước tiên tôi đã so sánh đầu ra được biên dịch bằng Compiler Explorer :

Chức năng được kiểm tra:

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 với -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

GCC 6.2 với -O3:

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

Ngả mũ xuống CLang, nó nhận ra rằng cả ba trường hợp đều có chức năng như nhau. Tuy nhiên, cách tiếp cận của Roy không được tối ưu hóa trong GCC, vì vậy YMMV.

Nó tương tự với Visual Studio; kiểm tra bản phát hành tháo gỡ x64 (VS2015) cho ba chức năng này, tôi có thể thấy rằng phần so sánh bằng với các trường hợp "mod" và "và", và lớn hơn một chút cho trường hợp "hoặc" của Roy:

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

Tuy nhiên, sau khi chạy một điểm chuẩn thực tế để so sánh ba tùy chọn này (mod đơn giản, bitwise hoặc, bitwise và), kết quả hoàn toàn bằng nhau (một lần nữa, Visual Studio 2005 x86 / x64, Bản dựng phát hành, không có trình gỡ lỗi đính kèm).

Tập hợp phát hành sử dụng testhướng dẫn cho andmodcác trường hợp, trong khi trường hợp của Roy sử dụng cmp eax,0FFFFFFFFhcách tiếp cận, nhưng nó không được kiểm soát và tối ưu hóa nhiều nên không có sự khác biệt trong thực tế.

Kết quả của tôi sau 20 lần chạy (i7 3610QM, gói điện năng Windows 10 được đặt thành Hiệu suất cao):

[Kiểm tra: Plain mod 2] THỜI GIAN AVERAGE: 689,29 ms (Tương đối khác: + 0,000%)
[Kiểm tra: Bitwise hoặc] THỜI GIAN AVERAGE: 689,63 ms (Tương đối khác: + 0,048%)
[Kiểm tra: Bitwise và] THỜI GIAN AVERAGE: 687,80 ms (Khác biệt tương đối: -0,217%)

Sự khác biệt giữa các tùy chọn này nhỏ hơn 0,3%, do đó, rõ ràng việc lắp ráp là bằng nhau trong mọi trường hợp.

Đây là mã nếu bất cứ ai muốn thử, với một cảnh báo mà tôi chỉ kiểm tra nó trên Windows (kiểm tra #if LINUXđiều kiện cho get_timeđịnh nghĩa và thực hiện nó nếu cần, lấy từ câu trả lời này ).

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

Tôi tin rằng bạn đã phạm phải tội lỗi của Hồng y; tạo ra một thứ cụ thể đến nỗi nó không đại diện cho một môi trường trong thế giới thực. Nhìn vào ngôn ngữ lắp ráp của bạn và chú ý số lượng đăng ký bạn đang sử dụng. Đánh giá cao cho nỗ lực, nhưng những kết quả này sẽ không theo kịp trong xử lý trong thế giới thực.

@RocketRoy: vì tất cả các kết quả đầu ra giống hệt nhau cho cả ba trường hợp (tốt, hơi tệ hơn cho chương trình của bạn trong một trường hợp), tôi không thực sự quan tâm có bao nhiêu thanh ghi được sử dụng. Nhưng một lần nữa, hãy thoải mái tạo và đăng chương trình / môi trường ví dụ như vậy, điều này sẽ khiến trình biên dịch nhầm lẫn để tạo ra một hội đồng tối ưu hơn trong một trong các trường hợp, tất cả những thứ khác đều bằng nhau.
Lou

Tôi luôn luôn thích lập trình viên cocky. Đó là một đặc điểm tốt cho một lập trình viên, nhưng trong một chương trình thực tế phức tạp hơn, phương pháp của tôi sẽ hoạt động tốt hơn so với trình biên dịch của bạn vì trình biên dịch có nhiều cách để giải quyết vấn đề để các hướng dẫn chồng chéo (trên các kiến ​​trúc Intel) tạo ra kết quả tốt hơn . Rất ít lập trình viên kỳ cựu có kinh nghiệm điểm chuẩn tốt sẽ thích điểm chuẩn của bạn, nhưng hãy tiếp tục làm tốt và nhớ chạy lại điểm chuẩn của bạn khi phát hành chip mới. Mọi thứ thay đổi theo thời gian.

3

Tôi biết đây chỉ là đường cú pháp và chỉ áp dụng trong .net nhưng còn phương pháp mở rộng thì sao ...

public static class RudiGroblerExtensions
{
    public static bool IsOdd(this int i)
    {
        return ((i % 2) != 0);
    }
}

Bây giờ bạn có thể làm như sau

int i = 5;
if (i.IsOdd())
{
    // Do something...
}

1
Mã đẹp. Đáng tiếc rằng nó sẽ cho rằng 2 là số lẻ và 3 thì không.
Anthony

Rất tiếc, xin lỗi ... logic của tôi là sai vòng ...
rudigrobler

3

Trong "danh mục sáng tạo nhưng khó hiểu" tôi cung cấp:

int isOdd(int n) { return n ^ n * n ? isOdd(n * n) : n; }

Một biến thể về chủ đề này dành riêng cho Microsoft C ++:

__declspec(naked) bool __fastcall isOdd(const int x)
{
    __asm
    {
        mov eax,ecx
        mul eax
        mul eax
        mul eax
        mul eax
        mul eax
        mul eax
        ret
    }
}

2

Phương pháp bitwise phụ thuộc vào biểu diễn bên trong của số nguyên. Modulo sẽ làm việc ở bất cứ nơi nào có toán tử modulo. Ví dụ: một số hệ thống thực sự sử dụng các bit cấp thấp để gắn thẻ (như ngôn ngữ động), do đó, x & 1 thô sẽ không thực sự hoạt động trong trường hợp đó.


2

IsOdd (int x) {return true; }

Bằng chứng về tính chính xác - xem xét tập hợp của tất cả các số nguyên dương và giả sử có một bộ số nguyên không trống không phải là số lẻ. Bởi vì các số nguyên dương được sắp xếp hợp lý, sẽ có một số nhỏ nhất không phải là số lẻ, mà bản thân nó khá kỳ lạ, nên rõ ràng số đó không thể có trong tập hợp. Do đó, bộ này không thể trống. Lặp lại cho các số nguyên âm ngoại trừ tìm số lớn nhất không lẻ.


2

Di động:

i % 2 ? odd : even;

Không thể truy cập:

i & 1 ? odd : even;

i << (BITS_PER_INT - 1) ? odd : even;

2

Như một số người đã đăng, có rất nhiều cách để làm điều này. Theo trang web này , cách nhanh nhất là toán tử mô đun:

if (x % 2 == 0)
               total += 1; //even number
        else
               total -= 1; //odd number

Tuy nhiên, đây là một số mã khác được đánh dấu bởi tác giả chạy chậm hơn so với hoạt động mô đun phổ biến ở trên:

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

Có bao nhiêu người thậm chí biết đến phương pháp Math.System.DivRem hoặc tại sao họ sẽ sử dụng nó ??



1

Để giải thích chi tiết hơn về phương pháp toán tử bitwise cho những người trong chúng ta đã không làm đại số boolean nhiều trong các nghiên cứu của chúng tôi, đây là một lời giải thích. Có lẽ không được sử dụng nhiều cho OP, nhưng tôi cảm thấy muốn làm rõ lý do tại sao SỐ & 1 hoạt động.

Xin lưu ý như ai đó đã trả lời ở trên, cách các số âm được thể hiện có thể dừng phương pháp này hoạt động. Trong thực tế, nó thậm chí có thể phá vỡ phương thức toán tử modulo vì mỗi ngôn ngữ có thể khác nhau về cách nó xử lý các toán hạng âm.

Tuy nhiên nếu bạn biết rằng SỐ sẽ luôn tích cực, thì điều này hoạt động tốt.

Như Tooony ở trên đã chỉ ra rằng chỉ có chữ số cuối cùng trong nhị phân (và từ chối) là quan trọng.

Một cổng logic Boolean ra lệnh rằng cả hai đầu vào phải là 1 (hoặc điện áp cao) cho 1 được trả về.

1 & 0 = 0.

0 & 1 = 0.

0 & 0 = 0.

1 & 1 = 1.

Nếu bạn biểu thị bất kỳ số nào dưới dạng nhị phân (tôi đã sử dụng biểu diễn 8 bit ở đây), số lẻ có 1 ở cuối, số chẵn có 0.

Ví dụ:

1 = 00000001

2 = 00000010

3 = 00000011

4 = 00000100

Nếu bạn lấy bất kỳ số nào và sử dụng bitwise AND (& trong java) thì nó sẽ trả về 00000001, = 1 có nghĩa là số đó là số lẻ. Hoặc 00000000 = 0, có nghĩa là số chẵn.

Ví dụ

Là số lẻ?

1 & 1 =

00000001 &

00000001 =

00000001 <- lẻ

2 & 1 =

00000010 &

00000001 =

00000000 <- Chẵn

54 & 1 =

00000001 &

00110110 =

00000000 <- Chẵn

Đây là lý do tại sao điều này hoạt động:

if(number & 1){

   //Number is odd

} else {

   //Number is even
}

Xin lỗi nếu điều này là dư thừa.


1

Số không chẵn lẻ | không http://tinyurl.com/oexhr3k

Trình tự mã 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))

Đầu ra:

   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

@ el.pescado, Cảm ơn bạn. Nếu Zero là chẵn thì nó có bao nhiêu cặp?

@ el.pescado, Ok, tôi đồng ý với bạn. Sau đó, nếu suy nghĩ một chút, tại sao chúng ta chia thành 2 (hai)? Những gì chúng ta muốn biết, khi chúng ta chia thành hai? Tại sao không chia thành 3, hoặc, 5, v.v.

@ el.pescado Bài viết Wikipedia này Parity of Zero là sai. Rất nhiều người đã bị đánh lừa bởi bài viết này. Hãy suy nghĩ trước khi nháy mắt.

1
Bạn đúng. Bây giờ tôi đã đọc các câu trả lời khác, tôi thấy bạn là toàn diện nhất :)
el.pescado

@ el.pescado. Cảm ơn bạn. :) Bây giờ bạn là bạn thân nhất của Zero. (ôm)

1
I execute this code for ODD & EVEN:

#include <stdio.h>
int main()
{
    int number;
    printf("Enter an integer: ");
    scanf("%d", &number);

    if(number % 2 == 0)
        printf("%d is even.", number);
    else
        printf("%d is odd.", number);
}

0

Vì lợi ích của cuộc thảo luận ...

Bạn chỉ cần nhìn vào chữ số cuối cùng trong bất kỳ số đã cho nào để xem nó là số chẵn hay lẻ. Đã ký, không dấu, tích cực, tiêu cực - tất cả đều giống nhau về vấn đề này. Vì vậy, điều này sẽ làm việc tất cả các vòng: -

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

Khóa ở đây nằm trong dòng mã thứ ba, toán tử chia thực hiện phép chia số nguyên, do đó kết quả bị thiếu phần phân số của kết quả. Vì vậy, ví dụ 222/10 sẽ cho 22 kết quả. Sau đó nhân nó lại với 10 và bạn có 220. Trừ đi số đó từ 222 gốc và bạn kết thúc bằng 2, bằng phép thuật là số giống với chữ số cuối cùng trong số ban đầu. ;-) Dấu ngoặc đơn ở đó để nhắc nhở chúng ta về thứ tự tính toán được thực hiện. Đầu tiên thực hiện phép chia và phép nhân, sau đó trừ kết quả khỏi số ban đầu. Chúng ta có thể loại bỏ chúng, vì mức độ ưu tiên cao hơn cho phép chia và phép nhân so với phép trừ, nhưng điều này mang lại cho chúng ta mã "dễ đọc hơn".

Chúng tôi có thể làm cho tất cả hoàn toàn không thể đọc được nếu chúng tôi muốn. Nó sẽ không tạo ra sự khác biệt nào cho trình biên dịch hiện đại: -

printf("%d%s\n",iToTest,0==(iToTest-iToTest/10*10)%2?" is even":" is odd");

Nhưng nó sẽ làm cho cách mã khó hơn để duy trì trong tương lai. Chỉ cần tưởng tượng rằng bạn muốn thay đổi văn bản cho các số lẻ thành "không chẵn". Sau đó, một người khác sau đó muốn tìm hiểu những thay đổi bạn đã thực hiện và thực hiện một svn diff hoặc tương tự ...

Nếu bạn không lo lắng về tính di động nhưng nhiều hơn về tốc độ, bạn có thể xem xét một chút ít quan trọng nhất. Nếu bit đó được đặt thành 1 thì đó là số lẻ, nếu là 0 thì đó là số chẵn. Trên một hệ thống endian nhỏ, như kiến ​​trúc x86 của Intel, nó sẽ giống như thế này: -

if (iToTest & 1) {
  // Even
} else {
  // Odd
}

Chính xác thì có gì sai khi chỉ dùng iToTest% 2 == 0? Bạn đang lãng phí một bộ phận trích xuất chữ số cuối cùng, do đó, bộ phận của bạn chậm gấp đôi so với mức cần thiết.
freespace

@freespace: Tôi lãng phí nhiều hơn thế, phải không? :-) Phép nhân và phép trừ cũng vậy. Nhưng điều gì là hiệu quả nhất giữa hai giải pháp tôi không dám nói. Không bao giờ tuyên bố đây là giải pháp nhanh nhất, hoàn toàn ngược lại nếu bạn đọc lại dòng đầu tiên của bài viết của tôi.
Tooony

@Tooony, ah, chiếc mũ hài hước của tôi rơi ra. Bây giờ nó đã chính thức trở lại: D Xin lỗi về điều đó :)
freespace

0

Nếu bạn muốn hiệu quả, hãy sử dụng toán tử bit ( x & 1), nhưng nếu bạn muốn có thể đọc được, hãy sử dụng modulo 2 ( x % 2)


-1: Nếu bạn muốn hiệu quả, hãy sử dụng một trong hai. Nếu bạn muốn nó là xách tay, sử dụng %. Nếu bạn muốn nó có thể đọc được, hãy sử dụng %. Hmmm, tôi thấy một mô hình ở đây.
Thomas Eding

@trinithis, không có mẫu nào và giải pháp này tốt hơn nhiều so với của bạn.
Dự bị

0

Kiểm tra chẵn hoặc lẻ là một nhiệm vụ đơn giản.

Chúng ta biết rằng bất kỳ số nào chia hết cho 2 đều là số lẻ khác.

Chúng tôi chỉ cần kiểm tra tính chia hết của bất kỳ số nào và để kiểm tra tính chia hết, chúng tôi sử dụng %toán tử

Kiểm tra chẵn sử dụng lẻ nếu khác

if(num%2 ==0)  
{
    printf("Even");
}
else
{
    printf("Odd");
}

Chương trình C để kiểm tra chẵn hoặc lẻ bằng cách sử dụng nếu khác

Sử dụng toán tử có điều kiện / Ternary

(num%2 ==0) printf("Even") : printf("Odd");

Chương trình C để kiểm tra chẵn hoặc lẻ bằng toán tử có điều kiện .

Sử dụng toán tử Bitwise

if(num & 1)  
{
    printf("Odd");
}
else 
{
    printf("Even");
}

và chính xác thì toán tử ternary ở đâu?
Beyondo

0

+ Nhanh hơn 66% >!(i%2) / i%2 == 0

int isOdd(int n)
{
    return n & 1;
}

Mã kiểm tra bit cuối của số nguyên nếu là 1 trong Nhị phân

Giải trình

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

Lưu ý bit ngoài cùng bên phải luôn là 1 cho các số lẻ .

các & Bitwise AND hành kiểm tra các bit ngoài cùng bên phải trong chúng tôi trở lại dòng nếu nó 1

Hãy nghĩ về nó là đúng và sai

Khi chúng ta so sánh n với 1 có nghĩa là 0001nhị phân (số không không quan trọng).
sau đó hãy tưởng tượng rằng chúng ta có số nguyên n với kích thước 1 byte.

Nó được biểu thị bằng các chữ số 8 bit / 8 nhị phân.

Nếu int n7 và chúng ta so sánh nó với 1 , thì giống như

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 là viết tắt của false và T là true.

Nó chỉ so sánh bit ngoài cùng bên phải nếu cả hai đều đúng. Vì vậy, tự động 7 & 1T rue.

Điều gì xảy ra nếu tôi muốn kiểm tra bit trước khi ngoài cùng bên phải?

Đơn giản chỉ cần thay đổi n & 1thành n & 22 đại diện 0010trong Nhị phân, v.v.

Tôi đề nghị sử dụng ký hiệu thập lục phân nếu bạn là người mới bắt đầu hoạt động bitwise
return n & 1;>> return n & 0x01;.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.