วิธีที่ง่ายที่สุดในการพลิกค่าบูลีน


125

ฉันแค่ต้องการพลิกบูลีนตามสิ่งที่มีอยู่แล้ว ถ้าเป็นจริง - ทำให้เป็นเท็จ หากเป็นเท็จ - ทำให้เป็นจริง

นี่คือรหัสที่ตัดตอนมาของฉัน:

switch(wParam) {

case VK_F11:
  if (flipVal == true) {
     flipVal = false;
  } else {
    flipVal = true;
  }
break;

case VK_F12:
  if (otherVal == true) {
     otherValVal = false;
  } else {
    otherVal = true;
  }
break;

default:
break;
}

คำตอบ:


341

คุณสามารถพลิกค่าได้ดังนี้:

myVal = !myVal;

ดังนั้นรหัสของคุณจะสั้นลงเป็น:

switch(wParam) {
    case VK_F11:
    flipVal = !flipVal;
    break;

    case VK_F12:
    otherVal = !otherVal;
    break;

    default:
    break;
}

7
ไม่เพียง แต่เป็นวิธีที่ง่ายที่สุด แต่ยังเป็นวิธีที่สะอาดที่สุดด้วย
sharptooth

ทั้งสองกรณีสามารถรวมเข้าด้วยกันได้เนื่องจากทำสิ่งเดียวกัน
David Allan Finch

1
เป็นค่าเริ่มต้น: break; จำเป็นจริงๆ? สวิตช์จะไม่จบลงเหมือนเดิมโดยไม่มีมันหรือ?
Chris Lutz

12
ค่าเริ่มต้น: ทำลาย; ไม่จำเป็น
Rob K

4
หากคุณกำลังสลับสิ่งที่คดเคี้ยวยาวเช่น object1-> system1.system2.system3.parameter1 การมีมาโคร TOGGLE (a) จะเป็นประโยชน์ ซึ่งจะช่วยป้องกันความผิดพลาดบางอย่างและทำให้ทุกอย่างอ่านได้ง่ายขึ้นบนหน้าจอแคบ ๆ
OJW

77

เห็นได้ชัดว่าคุณต้องการรูปแบบโรงงาน!

KeyFactory keyFactory = new KeyFactory();
KeyObj keyObj = keyFactory.getKeyObj(wParam);
keyObj.doStuff();


class VK_F11 extends KeyObj {
   boolean val;
   public void doStuff() {
      val = !val;
   }
}

class VK_F12 extends KeyObj {
   boolean val;
   public void doStuff() {
      val = !val;
   }
}

class KeyFactory {
   public KeyObj getKeyObj(int param) {
      switch(param) {
         case VK_F11:
            return new VK_F11();
         case VK_F12:
            return new VK_F12();
      }
      throw new KeyNotFoundException("Key " + param + " was not found!");
   }
}

: D

</sarcasm>

9
เราอาจเพิ่มรูปแบบซิงเกิลตันสำหรับโรงงานด้วย
Drew

@Orm สาเหตุที่คุณออม ? :)
mlvljr

3
สังเกตคำแนะนำที่ละเอียดอ่อนเพื่อเปลี่ยนไปใช้ Java!
หอยทากกล

อืม ... ฉันคิดว่าเราต้องการ C ++ รุ่นใหญ่อีกรุ่นสำหรับรุ่นนี้อาจเป็น C ++ / 51
0x6900

ไงพวก! ฉันคิดว่าแนวทางของคุณไม่ได้กลับมาอีก คุณต้องมี atomic_bool เป็นอย่างน้อยควรมี mutex หรือคิวเหตุการณ์ดีกว่า นอกจากนี้เราจำเป็นต้องมีรูปแบบการสังเกตการณ์เพื่อตรวจสอบสถานะของวาล
Marco Freudenberger

39

ถ้าคุณรู้ว่าค่าเป็น 0 หรือ 1 flipval ^= 1ที่คุณสามารถทำได้


1
เหตุใดจึงต้องใช้ตัวดำเนินการแบบบิตสำหรับการดำเนินการเชิงตรรกะ กลิ่นของความสับสนที่ไม่จำเป็นสำหรับฉัน
Mark Pim

5
@ มาร์ค: ขอโทษนะ เดาว่าฉันเชย แต่มันจะช่วยได้ถ้านิพจน์ค่า L ของคุณยาวมากคุณจึงไม่ต้องทำซ้ำ นอกจากนี้คุณสามารถพูดว่า flipval ^ = TRUE นั้นดีกว่าไหม
Mike Dunlavey

6
@Alnitak: คุณพูดถูกในบางสถานการณ์ ฉันเคยเห็นบางคนรวมบิตเข้าด้วยกันเพื่อ "ประหยัดพื้นที่" และทำราวกับว่าคำแนะนำในการเข้าถึงนั้นไม่ได้ใช้พื้นที่เลย
Mike Dunlavey

2
@Albert: ^เป็นพิเศษหรือผู้ประกอบการ 0^1เป็น1และเป็น1^1 0เช่นเดียวกับการเพิ่มหากคุณเพิกเฉยต่อบิตพกพา หรือคุณอาจคิดว่า - ถ้าบิตใดบิตหนึ่งเป็น 1 ผลลัพธ์จะเป็นค่าผกผันของอีกบิต หรือคุณอาจคิดว่าเป็นการถามคำถามว่าบิตทั้งสองนี้แตกต่างกันหรือไม่?
Mike Dunlavey

1
@MikeDunlavey หากคุณใช้อุปกรณ์ที่มี Flash 4M สำหรับพื้นที่โค้ดและ SRAM 3K สำหรับพื้นที่ข้อมูลนั่นเป็นวิธีการแสดงที่สมเหตุสมผล!
เอ็มเอ็ม

33

ทางออกที่ง่ายที่สุดที่ฉันพบ:

x ^= true;

12
x = !x;ไม่เพียง แต่สั้นลง แต่ยังอ่านง่ายขึ้นด้วย
Rodrigo

13
สังเกตว่าเช่นlongVariableName ^= true;นั้นสั้นกว่าอย่างชัดเจนlongVariableName = !longVariableName;และโปรแกรมเมอร์ทุกคนควรรู้ XOR
xamid

a ^= bหมายถึงa = a ^ bโดยที่^XOR หมายถึง สัญกรณ์a °= bสำหรับa = a ° bตัวดำเนินการใด ๆ°เป็นเรื่องปกติมากในไวยากรณ์ C / C ++ / C #
xamid

2
Anecdotal แต่ฉันเพิ่งเจอบรรทัดgRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value = !gRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value;นี้แน่นอนว่าสิ่งที่ต้องทำที่สุดคือการขยายไปยังหลายบรรทัดและใช้ตัวแปรชั่วคราวเพื่อเก็บอ็อบเจกต์ แต่gRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value ^= 1อ่านได้ง่ายขึ้นมากมีโอกาสเกิดข้อผิดพลาดน้อยลงและอักขระน้อยกว่าโค้ดดั้งเดิม .
Vortico

1
นอกจากนี้การทำซ้ำน้อยลงหมายถึงโอกาสที่จะลืมอัปเดตทั้งสองด้านของสมการน้อยลงในระหว่างการเปลี่ยนแปลงการพัฒนาอย่างรวดเร็ว / วัน / คืนของการเข้ารหัสที่ยาวนาน
Katastic Voyage

11

เพื่อดูข้อมูลหากแทนจำนวนเต็มฟิลด์ที่คุณต้องการเป็นบิตเดียวในประเภทที่ใหญ่กว่าให้ใช้ตัวดำเนินการ 'xor' แทน:

int flags;

int flag_a = 0x01;
int flag_b = 0x02;
int flag_c = 0x04;

/* I want to flip 'flag_b' without touching 'flag_a' or 'flag_c' */
flags ^= flag_b;

/* I want to set 'flag_b' */
flags |= flag_b;

/* I want to clear (or 'reset') 'flag_b' */
flags &= ~flag_b;

/* I want to test 'flag_b' */
bool b_is_set = (flags & flag_b) != 0;

9

ดูเหมือนว่าจะฟรีสำหรับทุกคน ... นี่คือความหลากหลายอีกประการหนึ่งซึ่งฉันคิดว่าอยู่ในหมวดหมู่ "ฉลาด" มากกว่าสิ่งที่ฉันแนะนำสำหรับรหัสการผลิต:

flipVal ^= (wParam == VK_F11);
otherVal ^= (wParam == VK_F12);

ฉันเดาว่าข้อดีคือ:

  • สั้นมาก
  • ไม่ต้องการการแตกแขนง

และข้อเสียที่ชัดเจนก็คือ

  • สั้นมาก

นี่ใกล้เคียงกับการแก้ปัญหาของ @ korona โดยใช้?: แต่ก้าวไปอีกขั้นหนึ่ง (เล็ก)


2
ตามลำดับของการดำเนินการฉันคิดว่าคุณสามารถละเว้นวงเล็บเพื่อให้สั้นลงได้ : O
Drew

8

เพียงเพราะวิธีการแทงบอลแบบแปลก ๆ ที่ฉันชอบในการสลับบูลไม่อยู่ในรายการ ...

bool x = true;
x = x == false;

ได้ผลเช่นกัน :)

(ใช่x = !x;ยิ่งชัดเจนและอ่านง่ายกว่า)


6

วิธีการแก้ปัญหา codegolf'ish จะเป็นดังนี้:

flipVal = (wParam == VK_F11) ? !flipVal : flipVal;
otherVal = (wParam == VK_F12) ? !otherVal : otherVal;

2

ฉันชอบวิธีแก้ปัญหาของ John T แต่ถ้าคุณต้องการใช้รหัสทั้งหมดคำสั่งของคุณจะลดลงตามเหตุผล:

//if key is down, toggle the boolean, else leave it alone.
flipVal = ((wParam==VK_F11) && !flipVal) || (!(wParam==VK_F11) && flipVal);
if(wParam==VK_F11) Break;

//if key is down, toggle the boolean, else leave it alone.
otherVal = ((wParam==VK_F12) && !otherVal) || (!(wParam==VK_F12) && otherVal);
if(wParam==VK_F12) Break;

คุณไม่ต้องตรวจสอบ wParam เทียบกับ VK_F11 และ VK_F12 ใช่หรือไม่
drby


0

เห็นได้ชัดว่าคุณต้องการโซลูชันที่ยืดหยุ่นซึ่งสามารถรองรับประเภทที่ปลอมตัวเป็นบูลีนได้ สิ่งต่อไปนี้ช่วยให้:

template<typename T>    bool Flip(const T& t);

จากนั้นคุณสามารถเชี่ยวชาญสิ่งนี้สำหรับประเภทต่างๆที่อาจแสร้งทำเป็นบูลีน ตัวอย่างเช่น:

template<>  bool Flip<bool>(const bool& b)  { return !b; }
template<>  bool Flip<int>(const int& i)    { return !(i == 0); }

ตัวอย่างการใช้โครงสร้างนี้:

if(Flip(false))  { printf("flipped false\n"); }
if(!Flip(true))  { printf("flipped true\n"); }

if(Flip(0))  { printf("flipped 0\n"); }
if(!Flip(1)) { printf("flipped 1\n"); }

ไม่ฉันไม่ซีเรียส


0

สำหรับจำนวนเต็มที่มีค่า 0 และ 1 คุณสามารถลอง:

value = abs(value - 1);

MWE ใน C:

#include <stdio.h>
#include <stdlib.h>
int main()
{
        printf("Hello, World!\n");
        int value = 0;
        int i;
        for (i=0; i<10; i++)
        {
                value = abs(value -1);
                printf("%d\n", value);
        }
        return 0;
}

0

เพียงเพราะฉันชอบถามรหัส ฉันขอเสนอว่าคุณสามารถใช้ประโยชน์จาก ternary ได้โดยทำสิ่งนี้:

ตัวอย่าง:

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