ฉันจะตรวจสอบว่าจำนวนเต็มเป็นเลขคี่หรือคู่ได้อย่างไร [ปิด]


193

ฉันจะตรวจสอบว่าหมายเลขที่กำหนดเป็นเลขคู่หรือคี่ใน C ได้อย่างไร


5
รุ่นที่ใช้ bitwise และ (&) มีประสิทธิภาพมากกว่ารุ่น modulo (%) มาก คุณควรเปลี่ยนคำตอบที่คุณเลือกให้ถูกต้อง
Stefan Rusek

6
ไม่น่าจะมีความหมาย - อาร์กิวเมนต์เป็นค่าคงที่ ง่ายสำหรับเครื่องมือเพิ่มประสิทธิภาพ
MSalters

2
ปัจจัยการอ่านในนี้เช่นกัน
Brian G

2
ในแอพพลิเคชั่นแบบฝังตัว (โลกที่ฉันใช้เวลาเขียนโปรแกรมส่วนใหญ่) โปรเซสเซอร์บางตัวมีหน่วยคำนวณทางคณิตศาสตร์แบบดั้งเดิมมากและไม่สามารถทำการหาร / โมดูลัสได้อย่างง่ายดาย ด้วยเหตุนี้ฉันมักจะใช้บิต - และเมธอดแทน อย่างไรก็ตามในซีพียูของเดสก์ท็อปสมัยใหม่จะไม่เป็นเช่นนั้น
bta

3
ฉันไม่เคยพบว่าการทำงานของโมดูลัสนั้นง่ายต่อการเข้าใจ เมื่อแรกที่ฉันจำเป็นต้องกำหนดแม้กระทั่งหรือคี่, หน้ากาก bitwise เป็นสิ่งแรกที่อยู่ในใจ มันค่อนข้างเป็นธรรมชาติเนื่องจากวิธีที่เรามักจะทำด้วยมือคือการดูหลักสำคัญน้อยที่สุดเพื่อดูว่ามันอยู่ใน {0 2 4 6 8} หรือ {1 3 5 7 9} นั่นแปลโดยตรงเพื่อดูบิตที่มีนัยสำคัญน้อยที่สุดเพื่อดูว่ามันเป็น 0 หรือ 1
P Daddy

คำตอบ:


449

ใช้โอเปอเรเตอร์แบบโมดูโล (%) เพื่อตรวจสอบว่ามีเศษที่เหลืออยู่เมื่อหารด้วย 2:

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

มีคนไม่กี่คนที่วิจารณ์คำตอบของฉันข้างต้นโดยระบุว่าการใช้ x & 1 คือ "เร็วกว่า" หรือ "มีประสิทธิภาพมากขึ้น" ฉันไม่เชื่อว่านี่เป็นกรณี

จากความอยากรู้ฉันได้สร้างโปรแกรมทดสอบสองเรื่องเล็กน้อย:

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

ฉันรวบรวมเหล่านี้ด้วย gcc 4.1.3 ในหนึ่งในเครื่องของฉัน 5 ครั้งที่แตกต่างกัน:

  • โดยไม่มีแฟล็กการปรับให้เหมาะสม
  • ด้วย -O
  • ด้วย -Os
  • ด้วย -O2
  • ด้วย -O3

ฉันตรวจสอบเอาต์พุตแอสเซมบลีของแต่ละคอมไพล์ (โดยใช้ gcc -S) และพบว่าในแต่ละกรณีเอาต์พุตสำหรับ and.c และ modulo.c เหมือนกัน (ทั้งคู่ใช้คำสั่ง andl $ 1,% eax) ฉันสงสัยว่านี่เป็นฟีเจอร์ "ใหม่" และฉันสงสัยว่ามันจะย้อนไปถึงเวอร์ชั่นเก่า ฉันยังสงสัยในปัจจุบันคอมไพเลอร์ (ทำใน 20 ปีที่ผ่านมา) ใด ๆ ที่ไม่ใช่ arcane คอมไพเลอร์เชิงพาณิชย์หรือโอเพนซอร์สขาดการเพิ่มประสิทธิภาพดังกล่าว ฉันจะทดสอบคอมไพเลอร์อื่น ๆ แต่ฉันไม่สามารถใช้ได้ในขณะนี้

หากใครก็ตามที่สนใจที่จะทดสอบคอมไพเลอร์และ / หรือเป้าหมายแพลตฟอร์มอื่น ๆ และได้รับผลที่แตกต่างกันฉันก็สนใจที่จะรู้

ในที่สุดรุ่นโมดูโล่รับประกันโดยมาตรฐานในการทำงานไม่ว่าจะเป็นจำนวนเต็มบวกลบหรือศูนย์โดยไม่คำนึงถึงการใช้งานของการแสดงจำนวนเต็มลงนาม บิต - และเวอร์ชันไม่ใช่ ใช่ฉันรู้ว่าส่วนประกอบสองอย่างนั้นค่อนข้างแพร่หลายดังนั้นนี่จึงไม่ใช่ปัญหา


11
คำถามถามโดยเฉพาะวิธีการทำใน C ดังนั้นฉันตอบใน C แม้ว่า chustar กล่าวว่าพวกเขาไม่สามารถทำงานใน Java ฉันไม่ได้อ้างสิทธิ์หรือบอกเป็นนัยว่านี่เป็นคำตอบของ Java ฉันไม่ทราบว่ามี Java ฉันคิดว่าฉันเพิ่งลงคะแนนครั้งแรกและสับสนว่าทำไม โอ้ดี
Chris Young

33
ฉันจะบอกว่าถ้า (x% 2! = 0) {/ * x แปลก * /} แต่ใครจะรู้ ไม่ทราบว่าเป็นจาวา
eugensk

9
มันได้รับ upvotes มากมายเพื่อแยกความแตกต่างจากผู้ปฏิบัติงานระดับบิตโดยไม่ต้องใช้กรรมของเราโหวตพวกเขาลง
wnoise

13
ฉันเห็นด้วยกับทุกอย่างยกเว้นสิ่งหนึ่ง: ฉันชอบที่จะแยกจำนวนเต็มและค่าความจริงออกแนวความคิดดังนั้นฉันชอบเขียนว่า "if (x% 2 == 1)" มันก็เหมือนกับคอมไพเลอร์ แต่อาจชัดเจนกว่าสำหรับคนเล็กน้อย นอกจากนี้คุณสามารถใช้รหัสเดียวกันในภาษาที่ไม่ได้แปลว่าไม่เป็นศูนย์จริง
Thomas Padron-McCarthy

46
มาตรฐานของฉัน เกณฑ์มาตรฐานคืออะไร? ฉันไม่ได้ทำการเปรียบเทียบ ฉันตรวจสอบภาษาแอสเซมบลีที่สร้างขึ้น สิ่งนี้ไม่มีอะไรเกี่ยวข้องกับ printf
หนุ่มคริส

207

พวกคุณมีประสิทธิภาพมากเกินไป สิ่งที่คุณต้องการคือ:

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

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

  return odd;
}

isEvenทำซ้ำสำหรับ

แน่นอนว่าไม่ได้ผลกับจำนวนลบ แต่ด้วยความฉลาดมาเสียสละ ...


17
หากคุณขว้างข้อยกเว้นการโต้เถียงเกี่ยวกับค่าลบและบันทึกไว้ในเอกสารว่าฟังก์ชั่นนี้คือ O (N) แล้วฉันก็จะดีกับสิ่งนี้
Jeffrey L Whitledge

7
รุ่นองค์กรจะต้องใช้ XML แน่นอนว่าทุกวันนี้คุณจะมีเว็บเซอร์วิสที่คุณสามารถสืบค้นได้
Martin Beckett

58
คุณควรปรับให้เหมาะสมด้วยตารางค้นหา
Weeble

1
ฉันเป็นพระจึงต้อง +1 ตัวแทน 6,999 ของคุณเข้าสู่สหัสวรรษใหม่
Eran Medan

7
มันยอดเยี่ยมมาก! เจ้านายของฉันบอกฉันว่าเรามีลูกค้าที่โกรธเพราะเขารู้สึกว่าใบอนุญาตองค์กรของเขาไม่ได้ให้อะไรมากไปกว่าใบอนุญาตมาตรฐาน ตอนนี้เราได้เพิ่มฟังก์ชั่นนี้ในโปรแกรมของเราและเพียงเพราะมันทำงานช้ากว่าเขาคิดว่าซอฟต์แวร์ของเขาทำงานได้ดีกว่า !!!
ฟิล

97

ใช้เลขคณิตบิต:

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

สิ่งนี้เร็วกว่าการใช้การหารหรือโมดูลัส


43
ฉันไม่คิดว่ามันยุติธรรมที่จะพูดว่าเร็วกว่าการใช้การหารหรือโมดูลัส มาตรฐาน C ไม่ได้พูดอะไรเกี่ยวกับประสิทธิภาพของตัวดำเนินการและคอมไพเลอร์ที่เหมาะสมจะสร้างโค้ดที่รวดเร็วสำหรับทั้งสอง ผมเองจะเลือกสำนวนที่สื่อสารความตั้งใจของฉันและ% ดูเหมือนว่าเหมาะสมเพิ่มเติมได้ที่นี่
หนุ่มคริส

21
ฉันชอบ (x & 1) ดีกว่าเพราะมันตรวจสอบว่าตัวเลขเป็นแบบเดียวกับที่คนทำหรือไม่: ตรวจสอบว่าตัวเลขสุดท้ายเป็นเลขคู่หรือคี่ ในความคิดของฉันมันสื่อสารความตั้งใจมากกว่าโมดูโลวิธี (ไม่ใช่ว่ามันสำคัญมาก)
Jeremy Ruten

2
คุณพูดถูกฉันคิดว่ามันเป็นเรื่องส่วนตัว แม้ว่าคำจำกัดความปกติของ "คู่" คือ "จำนวนเต็มที่หารด้วย 2" แต่ไม่ใช่ "จำนวนเต็มที่ลงท้ายด้วย 0, 2, 4, 6 หรือ 8" :-)
Chris Young

4
@TraumaPony - สำหรับ ANSI มาตรฐาน C และ Java ยุคแรกขึ้นอยู่กับระบบคอมพิวเตอร์ มันไม่ได้ระบุสิ่งที่ใช้แทนหมายเลขที่ลงนาม - คำชมของ 2, คำชมของ 1, โค้ดสีเทา, ฯลฯ แต่โมดูลัสเป็นโมดูลัสเสมอ
Aaron

9
ไม่ทำงานอย่างเป็นสากลสำหรับจำนวนลบ ดูรายละเอียดเพิ่มเติมได้ที่คำตอบนี้: stackoverflow.com/questions/160930/…สำหรับรายละเอียด
Andrew Edgecombe

36

[โหมดโจ๊ก = "เปิด"]

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


2
ว้าว ... นี่มันแย่กว่าโซลูชันของ SCdF! รุ่งโรจน์! ไม่ต้องโหวตเลย ... ไม่สามารถแนะนำสิ่งนี้ได้ แต่ขอบคุณสำหรับความตลก!
Wes P

1
ข้อดีของวิธีนี้คือใช้งานได้มากกว่าแค่ตัวเลข นอกจากนี้หากคุณแทนที่บรรทัดนี้: char bar = foo [foo.Length - 1]; ด้วยสิ่งนี้: double bar = Char.GetNumericValue (foo [foo.Length - 1]); จากนั้นมันจะทำงานกับระบบตัวเลขใด ๆ
Jeffrey L Whitledge

5
รายงานข้อผิดพลาด: 14.65 มีการรายงานว่าแปลกเมื่อไม่ควรทราบ
TheSoftwareJedi

4
ซอฟต์แวร์เจไดมันเป็น "คุณสมบัติ" ;)
Sklivvz

31
TheSoftwareJedi: 14.65 เป็นหนึ่งในจำนวนเต็มที่แปลกที่สุดที่ฉันเคยเห็น
Bruce Alderman

16

เพื่อตอบสนองต่อffpf - ฉันมีข้อโต้แย้งเดียวกันกับเพื่อนร่วมงานเมื่อหลายปีก่อนและคำตอบคือไม่มันไม่ทำงานกับจำนวนลบ

มาตรฐาน C กำหนดให้ตัวเลขลบสามารถแสดงได้ 3 วิธี:

  • ส่วนประกอบ 2
  • ส่วนประกอบ 1
  • เครื่องหมายและขนาด

การตรวจสอบเช่นนี้:

isEven = (x & 1);

จะใช้งานได้สำหรับส่วนเติมเต็มและ 2 ของเครื่องหมายและขนาด แต่ไม่ใช่สำหรับส่วนเสริม 1

อย่างไรก็ตามฉันเชื่อว่าสิ่งต่อไปนี้ใช้ได้กับทุกกรณี:

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

ขอบคุณ ffpf ที่ชี้ให้เห็นว่ากล่องข้อความกำลังกินทุกอย่างหลังจากตัวละครของฉันน้อยกว่า!


ฉันคิดว่าตัวอย่างรหัสที่สองของคุณไม่มีข้อความ
Jeff Yates

3
มาดูตัวเลขเหล่านั้นกัน!
thejh

14

สิ่งที่ดีคือ:

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

โปรดทราบว่าวิธีนี้ใช้การเรียกซ้ำแบบหางที่เกี่ยวข้องกับสองฟังก์ชัน มันสามารถนำมาใช้อย่างมีประสิทธิภาพ (กลายเป็นในขณะที่ / จนกว่าชนิดของห่วง) หากคอมไพเลอร์ของคุณรองรับการเรียกซ้ำหางเหมือนคอมไพเลอร์ Scheme ในกรณีนี้สแต็คไม่ควรล้น!


1
สิ่งนี้ไม่สามารถจัดการกับ isOdd (0) ได้
Steve McLeod

1
ฉันคิดว่าคุณมีลูปไม่สิ้นสุด (พร้อมการเรียกซ้ำแบบหาง) หรือการโอเวอร์โฟลว์แบบสแต็ก (โดยไม่มีการเรียกซ้ำแบบหาง) สำหรับ isOdd () ด้วยค่าใด ๆ หรือ isEven () ด้วยค่าคี่ใด ๆ มันจบลงด้วยความจริงเท่านั้น มันเป็นปัญหาการหยุดยั้งทั้งหมดอีกครั้ง
Jeffrey L Whitledge

7
โอ้แน่นอนแก้ไขด้วยไม่มีความคิดเห็นและทำให้ฉันดูเหมือนคนงี่เง่า ไม่เป็นไร.
Jeffrey L Whitledge

1
ตอนนี้คุณได้รับข้อผิดพลาดในการคอมไพล์: ใน isEven ไม่ทุกเส้นทางรหัสคืนค่า ไม่ฉันไม่ได้ลองใช้รหัสนี้จริงๆมันเป็นคอมไพเลอร์ในหัวของฉันที่บ่น
Jeffrey L Whitledge

5
ข้อผิดพลาดในการคอมไพล์: ไม่ใช่ทุกเส้นทางที่จะส่งคืนค่าความเกลียดชังที่จะทิ้งระเบิดคุณด้วยความคิดเห็นข้อผิดพลาดในโค้ดตัวอย่างของคุณ แต่จะเกิดอะไรขึ้นเมื่อคุณโทร isEven (5)
Kevin

11

ตัวเลขจะเท่ากับแม้ว่าเมื่อหารด้วยสองส่วนที่เหลือจะเป็น 0 ตัวเลขนั้นจะเป็นเลขคู่ถ้าหากหารด้วย 2 ส่วนที่เหลือจะเท่ากับ 1

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

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

วิธีการที่ยอดเยี่ยม!


วิธีการ Java ของคุณใช้งานไม่ได้เนื่องจาก num% 2 == -1 สำหรับจำนวนคี่ที่ติดลบ
WMR

นั่นเป็นเหตุผลที่คุณลงคะแนนฉัน
jjnguy

3
ฉันลงคะแนนเพราะฟังก์ชั่นของคุณใน C ใช้ตัวอักษรมากขึ้นในการพิมพ์มากกว่าที่มันทำ IE num% I คือ 7 ตัวอักษรรวมถึงช่องว่าง IsOdd (I) คือ 8 ตัวอักษร ทำไมคุณต้องสร้างฟังก์ชั่นที่มีความยาวมากกว่าเพียงแค่การดำเนินการ?
เควิน

13
@Kevin ในรหัสความคิดเห็นของฉันไม่ได้วัดจากตัวอักษร แต่ตามเวลาที่คุณเขียนมันรวมถึงคิด + เวลาดีบัก num% 2 ใช้เวลาคิดเป็นมิลลิวินาทีมากกว่า isOdd ตอนนี้เพิ่มตัวเลขทั่วโลกและคุณสูญเสียปีรวม นอกจากนี้ isOdd ยังสามารถทดสอบและตรวจสอบและได้รับการรับรองในที่สุดและข้อผิดพลาดฟรี (เช่นการจัดการตัวเลขติดลบ) ซึ่งเป็น num% 2 - นักพัฒนาบางคนมักจะมีข้อสงสัยและทำการทดลอง รหัสที่ดีคือรหัสที่คุณไม่ได้เขียนใช้ซ้ำเพียง 2 เซ็นต์ของฉัน
Eran Medan

2
@EranMedan ตรรกะเดียวกันนี้จะใช้กับการแทนที่ i ++ ด้วย IncrementByOne (i) และมันก็เป็นความคิดที่แย่ หากผู้พัฒนามีข้อสงสัยเกี่ยวกับสิ่งที่ num% 2 ทำฉันไม่ต้องการให้เขาหรือเธออยู่ใกล้กับรหัสของฉัน
เควิน


7

ผมจะบอกว่าหารด้วย 2 และถ้ามี 0 เหลือ, มันจะเป็นอย่างนั้น, มิฉะนั้นมันจะแปลก

การใช้มอดุลัส (%) ทำให้เป็นเรื่องง่าย

เช่น. 4% 2 = 0 ดังนั้น 4 จึงเป็น 5% 2 = 1 ดังนั้น 5 จึงเป็นเลขคี่


6

อีกหนึ่งวิธีแก้ปัญหา
(เด็กสามารถลงคะแนนได้)

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

  }
  return half1 == half2;
}

ไม่มีคุณไม่ได้ชนิดของเด็กที่ผมนับ :)
eugensk

ฉันกำลังจะลงคะแนนเสียงให้กับสิ่งนี้ แต่มันก็ช้าไปหน่อยกับจำนวนลบ :)
Chris Young

3
ตัวเลขทั้งหมดสดใสและเป็นบวก หรือคุณมีอคติต่อบางคน? :))
eugensk

3
ในคอมพิวเตอร์ตัวเลขทั้งหมดลบครั้งเดียวในที่สุดกลายเป็นบวก เราเรียกมันว่าแบบโรลโอเวอร์ของความสุข (ไม่สามารถใช้ได้กับ BIGNUMS, YMMY, ไม่ถูกต้องในทุกรัฐ)
Will Hartung

@ WillHartung "โรลโอเวอร์แห่งความสุข" เยี่ยมมาก! : D
thejh

6

ฉันจะสร้างตารางของ parities (0 ถ้าแม้ 1 ถ้าคี่) ของจำนวนเต็ม (ดังนั้นหนึ่งสามารถทำการค้นหา: 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 คือแม้ว่าจะมีจำนวนเต็ม k อยู่เช่นนั้นที่ n = 2k

จำนวนเต็ม n เป็นเลขคี่ถ้ามีจำนวนเต็ม k อยู่โดยที่ n = 2k + 1

นี่คือรหัสสำหรับมัน:

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-integers แทนค่าที่เป็นไปได้ของintการคอมไพล์ C ที่กำหนด (โปรดทราบว่า C-integers เป็นชุดย่อยของจำนวนเต็ม)

ทีนี้เราอาจกังวลว่าสำหรับ n ที่กำหนดใน C-integers ที่จำนวนเต็ม k ที่สอดคล้องกันอาจไม่มีอยู่ใน C-integers แต่มีหลักฐานเล็กน้อยก็สามารถแสดงให้เห็นว่าสำหรับจำนวนเต็มทั้งหมด n, | n | <= | 2n | (*) โดยที่ | n | คือ "n ถ้า n เป็นค่าบวกและ -n เป็นอย่างอื่น" ในคำอื่น ๆ สำหรับ n ทั้งหมดในจำนวนเต็มอย่างน้อยหนึ่งอย่างต่อไปนี้ถือ (ทั้งกรณี (1 และ 2) หรือกรณี (3 และ 4) จริง แต่ฉันจะไม่พิสูจน์ที่นี่)

กรณีที่ 1: n <= 2n

กรณีที่ 2: -n <= -2n

กรณีที่ 3: -n <= 2n

กรณีที่ 4: n <= -2n

ตอนนี้รับ 2k = n (เช่น Ak มีอยู่ถ้า n ยังอยู่ แต่ฉันจะไม่พิสูจน์ที่นี่ถ้า n ไม่ได้แล้ววนevenกลับล้มเหลวในการกลับก่อนแต่ทว่ามันไม่สำคัญ) แต่นี่ก็หมายถึง k <n ถ้า n ไม่ใช่ 0 โดย (*) และความจริง (ไม่ได้พิสูจน์ที่นี่อีก) ว่าสำหรับ m ทั้งหมด, z ในจำนวนเต็ม 2m = z หมายถึง z ไม่เท่ากับ m ที่ให้ m คือ 0 ไม่ใช่ในกรณีที่ n คือ 0, 2 * 0 = 0 ดังนั้น 0 ถึงแม้ว่าเราจะเสร็จแล้ว (ถ้า n = 0 แล้ว 0 อยู่ใน C-integers เพราะ n อยู่ใน C-integer ในฟังก์ชันevenดังนั้น k = 0 จึงอยู่ใน C-integers) ดังนั้น ak ในจำนวนเต็ม C มีอยู่สำหรับ n ใน C-integers หาก n เป็นเลขคู่

อาร์กิวเมนต์ที่คล้ายกันแสดงว่าถ้า n เป็นเลขคี่มีค่า ak ในจำนวนเต็ม C เช่นนั้น n = 2k + 1

ดังนั้นฟังก์ชั่นevenและoddการนำเสนอที่นี่จะทำงานได้อย่างถูกต้องสำหรับ C-integers ทั้งหมด


1
ฉันไม่ได้หมายถึงความผิด แต่ประเด็นของคำตอบนี้คืออะไร? i % 2มีขนาดเล็กมากและอาจมีประสิทธิภาพมากกว่า
GManNickG

2
@GMan: แต่นี่เป็นวิธีที่กำหนดมากขึ้น! นี่จะทำงานได้อย่างถูกต้องในการตรวจจับขอบกล่องทั้งหมด
Paddy

1
... และ (!!!) ถูกต้อง !!!
Thomas Eding

ฉันไม่สามารถบอกได้ว่าคุณพูดเล่นหรือไม่ : X %2ใช้ได้กับจำนวนเต็มทั้งหมด
GManNickG

1
+1: ฉันจะพูดว่า "คำตอบที่ดี" แต่ฉันคิดว่า "คำตอบที่น่าสนใจ" เหมาะสมกว่า
James Webster

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

2
อะไร? นั่นไม่ใช่ C #! นั่นคือบริสุทธิ์ C! :-P
ดาวเคราะห์น้อย

8
ฉันจะโยน WinForm รอบ ๆ ตัวเพื่อทำให้มันบริสุทธิ์ C # ...
Michael Petrotta

@mateusza: โดยปกติเมื่อคุณเห็น "บูล" ในมูลค่าบางส่วนหรืออื่น ๆ ใน C มันเป็นtypedefหรือ#defineหรือบางสิ่งบางอย่าง
David Thornley

2
@mateusza @David Thornley ใน C99 bool เป็นคุณสมบัติมาตรฐาน ( en.wikipedia.org/wiki/Stdbool.h )
fortran

1
พูดคุยเกี่ยวกับวงเล็บซ้ำซ้อนอย่างมหาศาล ...
โทมัส Eding

4

นี่คือคำตอบใน 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

ลองสิ่งนี้: return (((a>>1)<<1) == a)

ตัวอย่าง:

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

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

คุณช่วยอธิบายเรื่องนี้ได้มั้ย ฉันไม่คุ้นเคยกับผู้ประกอบการระดับบิตมาก
อับดุล

การเลื่อนไปทางขวาแล้วซ้ายจะเป็นศูนย์บิตสุดท้ายของคุณ (บิตที่ถูกที่สุด) หากหมายเลขใหม่เหมือนกันกับค่าดั้งเดิมหมายความว่าบิตสุดท้ายของหมายเลขเดิมคือ 0 ดังนั้นมันจึงเป็นเลขคู่ ดูคำตอบที่อัปเดตของฉัน
Kiril Aleksandrov

ขอบคุณฉันรับไปแล้ว
Abdul

ฉันไม่แน่ใจว่าวิธีใดเร็วกว่า ฉันไม่ได้พยายามเปรียบเทียบพวกเขา
Kiril Aleksandrov

นี่ไม่ใช่สิ่งที่สำคัญที่สุดของคุณหรือเปล่า? ปัญหาเกี่ยวกับ ints ที่ไม่ได้ลงนามในบางภาษาและ ints เชิงลบส่วนใหญ่ ...
Troyseph

4

การอ่านการสนทนานี้ค่อนข้างสนุกสนานฉันจำได้ว่าฉันมีฟังก์ชั่นตามเวลาจริงในโลกแห่งความเป็นจริงและทดสอบตัวเลขคี่และคู่ภายในวงหลัก มันเป็นฟังก์ชั่นพลังงานจำนวนเต็มโพสต์ที่อื่นใน StackOverflow ดังต่อไปนี้ มาตรฐานค่อนข้างน่าแปลกใจ อย่างน้อยในฟังก์ชั่นของโลกแห่งความเป็นจริงโมดูโล่จะช้ากว่าและมีความหมายมาก ผู้ชนะโดยระยะขอบกว้างซึ่งต้องใช้เวลา 67% ของโมดูโลเป็นวิธีการหรือ (|)และไม่พบที่ใดในหน้านี้

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

สำหรับ 300 ล้านลูปการกำหนดเวลามาตรฐานมีดังนี้

3.962 และวิธีการหน้ากาก

4.851 & วิธีการ

5.850 วิธีการ%

สำหรับคนที่คิดว่าทฤษฎีหรือรายการภาษาแอสเซมบลีตั้งหลักแหล่งข้อโต้แย้งเช่นนี้ควรเป็นเรื่องเตือน มีสิ่งต่าง ๆ ในสวรรค์และโลก Horatio มากกว่าที่คุณฝันไว้ในปรัชญาของคุณ


1
ดีกว่าที่จะใช้unsigned xเป็นคือการดำเนินการกำหนดพฤติกรรมเมื่อx = x >> 1; x < 0ไม่ชัดเจนว่าทำไมxและOrMaskแตกต่างกันในประเภท ง่ายพอที่จะเขียนใหม่โดยใช้การwhile(x)ทดสอบ
chux - Reinstate Monica

2
ฉันสงสัยว่าคอมไพเลอร์ที่คุณใช้มาตรฐานนี้เนื่องจากคอมไพเลอร์ส่วนใหญ่ควรจะเพียงพอที่สมาร์ทการรวบรวมกรณีใช้ค่าที่เหมาะสม% 2 &ฉันเพิ่งทดสอบสิ่งนี้และผลลัพธ์จะเหมือนกันอย่างสมบูรณ์ (VS2015, Release builds พร้อมการปรับแต่งทั้งหมดทั้ง x86 และ x64) คำตอบที่ได้รับการยอมรับยังระบุสิ่งนี้สำหรับ GCC (เขียนในปี 2008)
Lou

2
ปัญหาเกี่ยวกับการโพสต์นี้คือสถานที่ที่บิตorจะเร็วกว่าที่andไม่น่าเป็นไปได้สูงในแพลตฟอร์ม / คอมไพเลอร์ แม้ว่าจะมีแพลตฟอร์มที่แปลกประหลาด / คอมโบคอมไพเลอร์ (และคุณยังไม่ได้โพสต์ไม่ว่าจะเป็นหรือรหัสที่ใช้ในการทำเกณฑ์มาตรฐาน) ทั้งนี้ขึ้นอยู่กับคอมไพเลอร์อื่น ๆ ที่ทำตัวเหมือนกัน ดังนั้นอย่างที่ฉันเขียนฉันสงสัยว่าแพล็ตฟอร์ม / คอมไพเลอร์นี้ผ่านการทดสอบเพราะฉันเกือบแน่ใจว่ามันไม่ได้วัดอย่างถูกต้อง
Lou

2
ไม่เรียกคุณว่าคนโกหกเพียงอ้างสิทธิ์ด้วยความมั่นใจสูงว่าคุณไม่ได้วัดอย่างถูกต้อง ไม่จำเป็นต้องเรียกผมว่าคนขับรถบรรทุกยังอ่านความคิดเห็นเดิมของฉัน: ฉันไม่ทำให้มาตรฐานและผลการวิจัยเป็นไปตามคาดสมบูรณ์เหมือนกันในทุกกรณีที่สาม (เชื่อมั่นของ ~ 3 ซิกหลังจากทำงานในแต่ละการทดสอบ 10 ครั้งสำหรับ 500.000 .000 การวนซ้ำ) หากคุณมีอาชีพที่มีชื่อเสียงมายาวนานลองถอยกลับมาและคิดว่าการเรียกร้องของคุณสมเหตุสมผลหรือไม่แล้วโพสต์รหัสจริงที่ใช้ทำเกณฑ์มาตรฐาน มิฉะนั้นโพสต์คือสิ่งที่ฉันเชื่อว่ามันเป็นเพียงความผิดพลาดในการวัด
Lou

1
เสร็จสิ้น
Lou

4

นี่คือการติดตามการสนทนากับ @RocketRoy เกี่ยวกับคำตอบของเขาแต่อาจเป็นประโยชน์กับทุกคนที่ต้องการเปรียบเทียบผลลัพธ์เหล่านี้

tl; drจากสิ่งที่ฉันได้เห็นแนวทางของ Roy ( (0xFFFFFFFF == (x | 0xFFFFFFFE)) ไม่ได้รับการปรับอย่างสมบูรณ์ให้x & 1เป็นmodแนวทาง แต่ในทางปฏิบัติเวลาที่ใช้ควรจะเปิดออกเท่ากันในทุกกรณี

ดังนั้นก่อนอื่นฉันเปรียบเทียบผลลัพธ์ที่คอมไพล์ด้วยCompiler Explorer :

ฟังก์ชั่นการทดสอบ:

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

GCC 6.2 ด้วย -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

เมื่อพูดถึง CLang เราตระหนักว่าทั้งสามคดีมีความเท่าเทียมกันทางหน้าที่ อย่างไรก็ตามวิธีการของ Roy ไม่ได้รับการปรับให้เหมาะสมใน GCC ดังนั้น YMMV

มันคล้ายกับ Visual Studio; การตรวจสอบ disassembly Release x64 (VS2015) สำหรับฟังก์ชั่นทั้งสามนี้ฉันจะเห็นว่าส่วนการเปรียบเทียบมีค่าเท่ากันสำหรับ "mod" และ "และ" และ "case" และใหญ่กว่าเล็กน้อยสำหรับ 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)

อย่างไรก็ตามหลังจากรันเกณฑ์มาตรฐานที่แท้จริงสำหรับการเปรียบเทียบสามตัวเลือกเหล่านี้ (mod ธรรมดา, bitwise หรือ, Bitwise และ) ผลลัพธ์ที่ได้นั้นมีค่าเท่ากันอย่างสมบูรณ์ (อีกครั้ง Visual Studio 2005 x86 / x64, Build build, ไม่มี debugger

ชุดประกอบที่ใช้testคำสั่งandและmodเคสในขณะที่เคสของ Roy ใช้cmp eax,0FFFFFFFFhวิธีการนี้ แต่มันไม่ได้รับการควบคุมและปรับให้เหมาะสมดังนั้นจึงไม่มีความแตกต่างในทางปฏิบัติ

ผลลัพธ์ของฉันหลังจากการรัน 20 ครั้ง (i7 3610QM, แผนการใช้พลังงานของ Windows 10 กำหนดเป็นประสิทธิภาพสูง):

[ทดสอบ: mod ธรรมดา 2] เวลาเฉลี่ย: 689.29 ms (ความแตกต่างสัมพัทธ์: + 0.000%)
[ทดสอบ: บิตหรือ] เวลาโดยเฉลี่ย: 689.63 ms (สัมพัทธ์ต่าง: + 0.048%)
[ทดสอบ: บิตและ] เวลาโดยเฉลี่ย: 687.80 มิลลิวินาที (ความต่างสัมพัทธ์: -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;
}

ฉันเชื่อว่าคุณได้ทำข้อตกลงในการเปรียบเทียบกับพระคาร์ดินัล การสร้างที่เฉพาะเจาะจงมากมันไม่ได้เป็นตัวแทนของสภาพแวดล้อมโลกแห่งความจริง ดูภาษาแอสเซมบลีของคุณและสังเกตว่ามีกี่รีจิสเตอร์ที่คุณใช้อยู่ คะแนนสูงสำหรับความพยายาม แต่ผลลัพธ์เหล่านี้จะไม่ถือในการประมวลผลในโลกแห่งความจริง

@RocketRoy: เนื่องจากเอาต์พุตทั้งหมดเหมือนกันสำหรับทั้งสามกรณี (ดีกว่าเล็กน้อยสำหรับโปรแกรมของคุณในกรณีเดียว) ฉันไม่สนใจว่าจะมีการใช้กี่รีจิสเตอร์ แต่อีกครั้งอย่าลังเลที่จะสร้างและโพสต์ตัวอย่างโปรแกรม / สภาพแวดล้อมซึ่งจะสร้างความสับสนให้คอมไพเลอร์เพื่อสร้างแอสเซมบลีที่เหมาะสมที่สุดในกรณีใดกรณีหนึ่งทุกสิ่งเท่าเทียมกัน
Lou

ฉันชอบโปรแกรมเมอร์ที่อวดดีเสมอ มันเป็นลักษณะที่ดีสำหรับโปรแกรมเมอร์ที่จะมี แต่ในโปรแกรมที่ซับซ้อนกว่าในโลกแห่งความเป็นจริงวิธีการของฉันจะทำงานได้ดีกว่าของคุณเพราะคอมไพเลอร์มีวิธีแก้ไขปัญหามากกว่าเพื่อให้คำแนะนำซ้อนทับกัน (บนสถาปัตยกรรม Intel) . โปรแกรมเมอร์ทหารผ่านศึกน้อยมากที่มีประสบการณ์การเปรียบเทียบที่ดีจะต้องการเกณฑ์มาตรฐานของคุณ แต่ควรติดตามการทำงานที่ดีและอย่าลืมเรียกใช้การวัดประสิทธิภาพของคุณอีกครั้งเมื่อมีการออกชิปใหม่ สิ่งต่าง ๆ เปลี่ยนแปลงตลอดเวลา

3

ฉันรู้ว่านี่เป็นเพียงวากยสัมพันธ์น้ำตาลและใช้ได้เฉพาะใน. netแต่สิ่งที่เกี่ยวกับวิธีการขยาย ...

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

ตอนนี้คุณสามารถทำดังต่อไปนี้

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

1
รหัสที่ดี น่าเสียดายที่มันจะอ้างว่า 2 เป็นคี่และ 3 ไม่ใช่
แอนโธนี

โอ๊ะขอโทษ ... ตรรกะของฉันผิดไปตลอด ...
rudigrobler

3

ในหมวดหมู่ "สร้างสรรค์ แต่สับสน" ฉันขอเสนอ:

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

ตัวแปรในชุดรูปแบบนี้เฉพาะสำหรับ 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

วิธีการ bitwise ขึ้นอยู่กับการแสดงภายในของจำนวนเต็ม โมดูโล่จะทำงานได้ทุกที่ที่มีโอเปอเรเตอร์แบบโมดูโล่ ตัวอย่างเช่นบางระบบใช้บิตระดับต่ำจริง ๆ สำหรับการแท็ก (เช่นภาษาไดนามิก) ดังนั้น raw x & 1 จะไม่ทำงานในกรณีนั้น


2

IsOdd (int x) {return true; }

หลักฐานความถูกต้อง - พิจารณาชุดของจำนวนเต็มบวกทั้งหมดและสมมติว่ามีชุดจำนวนเต็มที่ไม่ว่างที่ไม่ใช่เลขคี่ เนื่องจากเลขจำนวนเต็มบวกนั้นได้รับคำสั่งอย่างดีจะมีจำนวนน้อยที่สุดไม่ใช่คี่ซึ่งในตัวมันเองค่อนข้างแปลกดังนั้นชัดเจนว่าตัวเลขไม่สามารถอยู่ในชุดได้ ดังนั้นชุดนี้จะต้องไม่ว่างเปล่า ทำซ้ำสำหรับจำนวนเต็มลบยกเว้นมองหาจำนวนที่ไม่ผิด



2

ในขณะที่บางคนโพสต์มีหลายวิธีในการทำเช่นนี้ ตามเว็บไซต์นี้วิธีที่เร็วที่สุดคือตัวดำเนินการโมดูลัส

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หรือทำไมพวกเขาถึงใช้มัน



1

เพื่อให้รายละเอียดเพิ่มเติมเกี่ยวกับวิธีการตัวดำเนินการระดับบิตสำหรับพวกเราที่ไม่ได้ทำพีชคณิตแบบบูลมากในระหว่างการศึกษาของเรานี่คือคำอธิบาย อาจไม่ได้ใช้ประโยชน์อย่างมากกับ OP แต่ฉันรู้สึกอยากทำให้มันชัดเจนว่าทำไม NUMBER & 1 ถึงทำงาน

โปรดทราบเช่นเดียวกับใครบางคนตอบข้างต้นวิธีการแสดงจำนวนลบสามารถหยุดวิธีนี้ได้ ในความเป็นจริงมันยังสามารถแบ่งวิธีโอเปอเรเตอร์ของโมดูโล่ด้วยเช่นกันเนื่องจากแต่ละภาษาสามารถแตกต่างกันในวิธีที่มันเกี่ยวข้องกับตัวถูกดำเนินการเชิงลบ

อย่างไรก็ตามถ้าคุณรู้ว่า NUMBER จะเป็นค่าบวกเสมอ

เนื่องจาก Tooony ด้านบนได้ระบุว่าเฉพาะเลขตัวสุดท้ายในระบบไบนารี่

ตรรกะบูลีนและเกทกำหนดว่าอินพุตทั้งสองต้องเป็น 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

หากคุณใช้ตัวเลขใด ๆ และใช้ bitwise 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
}

ขออภัยถ้านี่ซ้ำซ้อน


1

Number Zero parity | ศูนย์http://tinyurl.com/oexhr3k

ลำดับรหัสหลาม

# 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

@ el.pescado ขอบคุณ ถ้าศูนย์ยังเท่ากันมีกี่คู่?

@ el.pescado โอเคฉันเห็นด้วยกับคุณ ถ้าคิดสักหน่อยทำไมเราถึงหาร 2 (สอง)? สิ่งที่เราอยากรู้เมื่อเราแบ่งเป็นสอง ทำไมไม่แบ่งเป็น 3 หรือ 5 เป็นต้น

@ el.pescado บทความ Wikipedia นี้Parity of Zeroผิด ผู้คนจำนวนมากถูกหลอกโดยบทความนี้ คิดก่อน Wink

1
คุณถูก. ตอนนี้ฉันได้อ่านคำตอบอื่น ๆ แล้วฉันพบว่าคุณครอบคลุมมากที่สุด :)
el.pescado

@ el.pescado ขอบคุณ. :) ตอนนี้คุณเป็นเพื่อนที่ดีที่สุดของ Zero (กอด)

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

เพื่อการอภิปราย ...

คุณต้องดูตัวเลขสุดท้ายในจำนวนที่กำหนดเพื่อดูว่าเป็นเลขคู่หรือคี่ ลงนามไม่ได้ลงนามในเชิงบวกเป็นลบ - พวกเขาจะเหมือนกันทั้งหมดเกี่ยวกับเรื่องนี้ ดังนั้นนี่ควรจะใช้ได้ทุกรอบ: -

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

กุญแจนี่อยู่ในบรรทัดที่สามของรหัสผู้ดำเนินการหารทำการหารจำนวนเต็มดังนั้นผลลัพธ์จะหายไปส่วนเศษส่วนของผล ตัวอย่างเช่น 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 มันจะเป็นเลขคู่ ในระบบ endian เล็ก ๆ น้อย ๆ เช่นสถาปัตยกรรม x86 ของ Intel มันจะเป็นแบบนี้: -

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

เกิดอะไรขึ้นกับการไปของ iToTest% 2 == 0 คุณกำลังสูญเสียแผนกที่แยกตัวเลขสุดท้ายดังนั้นคุณจึงช้ากว่าที่ควรจะเป็นสองเท่า
FreeSpace

@ frereace: ฉันเสียมากกว่านั้นใช่ไหม? :-) การคูณและการลบด้วย แต่สิ่งที่มีประสิทธิภาพมากที่สุดระหว่างสองโซลูชันที่ฉันไม่กล้าพูด ไม่เคยอ้างว่านี่เป็นวิธีแก้ปัญหาที่เร็วที่สุดตรงกันข้ามถ้าคุณอ่านบรรทัดแรกของโพสต์ของฉันอีกครั้ง
Tooony

@ Tooony อ่าหมวกอารมณ์ขันของฉันร่วงหล่น ตอนนี้กลับมาแล้วอย่างเป็นทางการ: D ขอโทษด้วย :)
ต๊อ

0

ถ้าคุณต้องการที่จะมีประสิทธิภาพใช้ตัวดำเนินการระดับบิต ( x & 1) แต่ถ้าคุณต้องการให้สามารถอ่านได้ใช้ modulo 2 ( x % 2)


-1: ถ้าคุณต้องการให้มีประสิทธิภาพใช้อย่างใดอย่างหนึ่ง %ถ้าคุณอยากให้มันเป็นแบบพกพาใช้งาน %หากคุณต้องการที่จะอ่านได้ใช้ อืมฉันเห็นรูปแบบที่นี่
Thomas Eding

@trinithis ไม่มีรูปแบบและวิธีนี้ดีกว่าของคุณมาก
Subs

0

การตรวจสอบคู่หรือคี่เป็นงานง่าย

เรารู้ว่าจำนวนใด ๆ ที่หารด้วย 2 ได้อย่างเลขคู่นั้นก็เลขคี่

เราเพียงแค่ต้องตรวจสอบความหารของจำนวนใด ๆ และสำหรับการตรวจสอบความหารที่เราใช้ %ประกอบการ

ตรวจสอบการใช้งานที่แปลกแม้กระทั่งถ้าอื่น

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

โปรแกรม C เพื่อตรวจสอบว่าคู่หรือคี่ใช้ถ้าอื่น

การใช้ตัวดำเนินการตามเงื่อนไข / ที่สาม

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

โปรแกรม C เพื่อตรวจสอบคี่ได้หรือใช้ประกอบการที่มีเงื่อนไข

ใช้ตัวดำเนินการ Bitwise

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

และผู้ประกอบการที่สามคือที่ไหน?
Beyondo

0

+ 66%เร็วขึ้น>!(i%2) / i%2 == 0

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

รหัสจะตรวจสอบบิตสุดท้ายของจำนวนเต็มถ้าเป็น1ใน Binary

คำอธิบาย

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 เสมอสำหรับหมายเลขคี่

ตัวดำเนินการ& bitwise AND ตรวจสอบบิตขวาสุดในบรรทัดส่งคืนของเราหากเป็น 1

คิดว่ามันเป็นเรื่องจริง & เท็จ

เมื่อเราเปรียบเทียบnกับ 1ซึ่งหมายถึงเป็น0001เลขฐานสอง (จำนวนศูนย์ไม่สำคัญ)
ลองสมมุติว่าเรามีจำนวนเต็มnด้วยขนาด 1 ไบต์

มันจะถูกแทนด้วยตัวเลข 8-bit / 8-binary

ถ้า 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หมายถึง false และTสำหรับ true

มันเปรียบเทียบเพียงบิตที่ถูกต้องที่สุดหากพวกเขาเป็นทั้งจริง ดังนั้นโดยอัตโนมัติ7 & 1คือT rue

ถ้าฉันต้องการตรวจสอบบิตก่อนที่ถูกต้อง?

เพียงแค่เปลี่ยน n & 1ไปn & 2ซึ่งแสดงให้เห็นถึง 2 0010ในไบนารีและอื่น ๆ

ผมขอแนะนำให้ใช้เลขฐานสิบหกถ้าคุณจะเริ่มต้นในการดำเนินงาน Bitwise >>
return n & 1;return n & 0x01;

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.