จากภาษาธรรมชาติถึงการแสดงออก C ++


9

ที่ได้รับมอบหมาย:

แปลนิพจน์ภาษาธรรมชาติต่อไปนี้เป็นนิพจน์ C ++ สมมติว่าตัวแปรทั้งหมดเป็นตัวเลขที่ไม่เป็นลบหรือบูลีน (ของค่าจริงหรือเท็จ)

ภาษาธรรมชาติ:

ทั้ง a และ b เป็นเท็จหรือ c เป็นจริง แต่ไม่ใช่ทั้งสองอย่าง

ทางออกของฉัน:

(a==0 && b==0)xor(c==1)

อาจารย์แก้ปัญหา:

(!a && !b) != c

คำถาม:

  1. ฉันคิดว่าฉันเข้าใจวงเล็บแรกเล็กน้อยโดยพูดว่า "ไม่ใช่ -a" และ "ไม่ -b" ฉันคิดว่า a และ b ต้องผิดโดยให้ ab ถือว่าเป็นจุดเริ่มต้นที่ไม่ใช่ศูนย์ ขวา?

  2. แต่ส่วนที่บอกว่า "ไม่เท่ากันกับ c"

  3. ฉันไม่เข้าใจวิธีแก้ปัญหาของศาสตราจารย์ทุกคนสามารถทำลายมันให้ฉันได้หรือไม่?

ขอขอบคุณสำหรับความช่วยเหลือ!


โดยทั่วไปฉันจะต้องระมัดระวังในการแปลภาษานิพจน์บูลีนเป็นรหัสการแปล ความผิดพลาดที่พบบ่อยคือการแปลระดับ "A เท่ากับ B หรือ C" เพื่อแทนa == b or c a == b or a ==cปัญหาคือการพูด lanuage ไม่แม่นยำและจริง ๆ แล้วการตีความทั้งสองอาจถูกต้อง
idclev 463035818

คำตอบ:


5

ฉันจะคิดว่าa, bและมีcbool

มาวาดตารางความจริงกันบ้าง:

| a | !a | a==1 | a==0 |
| 0 |  1 |   0  |   1  |
| 1 |  0 |   1  |   0  |

ในขณะที่คุณสามารถดูaและa==1เทียบเท่าและ!aและa==0นอกจากนี้ยังมีเทียบเท่าเพื่อให้เราสามารถเขียนเป็น(a==0 && b==0)xor(c==1)(!a && !b) xor c

ตอนนี้ตารางความจริงเพิ่มเติมบางส่วน:

| a | b | a xor b | a != b |
| 0 | 0 |    0    |    0   |
| 0 | 1 |    1    |    1   |
| 1 | 0 |    1    |    1   |
| 1 | 1 |    0    |    0   |

ดังนั้นa!=bคือการเทียบเท่าa xor bเพื่อให้เราสามารถเขียนไป(!a && !b) xor c (!a && !b)!=cอย่างที่คุณเห็นโซลูชั่นของคุณนั้นเทียบเท่ากันเพียงแค่เขียนด้วย 'สัญลักษณ์' ที่แตกต่างกัน


UPD : ลืมพูดถึง มีเหตุผลว่าทำไมทางออกของศาสตราจารย์จึงเป็นเช่นนั้น

วิธีแก้ปัญหาของอาจารย์นั้นเป็นไปในทางที่ผิดมากกว่า ในขณะที่วิธีการแก้ปัญหาของคุณถูกต้องทางเทคนิคมันไม่ได้เป็นรหัส C ++

ปัญหาแรกคือการใช้งานประเภทต่างๆ วิธีการแก้ปัญหาของคุณอาศัยการแปลงระหว่างintและboolเมื่อคุณเปรียบเทียบค่าบูลีนไปยังหมายเลขหรือการใช้งานxorซึ่งเป็น 'บิตฉลาดพิเศษหรือ' ผู้ประกอบการที่กระทำต่อints เกินไป ใน C ++ ที่ทันสมัยเป็นที่นิยมมากขึ้นในการใช้ค่าประเภทที่ถูกต้องและไม่ต้องพึ่งพาการแปลงเช่นบางครั้งพวกเขาไม่ชัดเจนและยากที่จะให้เหตุผล สำหรับboolค่าดังกล่าวคือtrueและfalseแทน1และ0ตามลำดับ นอกจากนี้ยัง!=มีความเหมาะสมมากกว่าxorเพราะในขณะที่เทคนิคboolถูกเก็บเป็นตัวเลข แต่ sematically คุณไม่ได้ตัวเลขใด ๆ เพียงค่าตรรกะ

ประเด็นที่สองก็เกี่ยวกับสำนวนเช่นกัน มันอยู่ที่นี่: a == 0. มันไม่ถือว่าเป็นการปฏิบัติที่ดีในการเปรียบเทียบนิพจน์บูลีนกับค่าคงที่บูลีน อย่างที่คุณรู้อยู่แล้วว่าa == trueมันเทียบเท่ากับ just aและa == falsejust !aหรือnot a(ฉันชอบอันหลัง) เพื่อให้เข้าใจถึงสาเหตุที่การเปรียบเทียบไม่ดีเพียงเปรียบเทียบโค้ดสองชุดและตัดสินใจซึ่งชัดเจนกว่า:

if (str.empty() == false) { ... }

VS

if (not str.empty()) { ... }

1
ในขณะที่ถูกต้องทางเทคนิคคำตอบนี้หลีกเลี่ยงการพูดคุยเกี่ยวกับประเภทและสำนวน C ++ ซึ่งน่าจะเป็นประเด็นของการฝึกนี้
Konrad Rudolph

@ KonradRudolph ใช่แล้วฉันลืมพูดไปหมดแล้ว บางทีฉันอาจจะแก้ไขคำตอบของฉันขอบคุณ
Yuri Kovalenko

3

คิดว่าบูลีนไม่ใช่บิต

โดยสรุปคำตอบของอาจารย์ของคุณนั้นดีกว่า (แต่ก็ยังพูดผิดดูเคร่งครัดมากขึ้น) เพราะมันใช้โอเปอเรเตอร์บูลีนแทนโอเปอเรเตอร์บิตไซด์และรักษาบูลีนเป็นจำนวนเต็ม การแสดงออกc==1เพื่อเป็นตัวแทนของ "C เป็นความจริง" ไม่ถูกต้องเพราะถ้าคอาจเป็นตัวเลข (ตามที่ได้รับมอบหมายตามที่ระบุไว้) แล้วใด ๆ ที่ไม่ใช่ศูนย์ค่าของ c trueคือจะได้รับการยกย่องในฐานะที่เป็นตัวแทนของ

ดูคำถามนี้ว่าเหตุใดจึงไม่ควรเปรียบเทียบบูลีนกับ 0 หรือ 1 แม้ว่าจะปลอดภัยก็ตาม

หนึ่งในเหตุผลที่ดีมากที่จะไม่ใช้xorเป็นที่ว่านี้เป็นบิตที่ชาญฉลาดการดำเนินการ แต่เพียงผู้เดียวหรือ มันเกิดขึ้นกับตัวอย่างของคุณเพราะทั้งด้านซ้ายและด้านขวาเป็นนิพจน์บูลีนที่แปลงเป็น 1 หรือ 0 (ดูอีก1 )

!=แต่เพียงผู้เดียวหรือบูลีนในความเป็นจริง

ทำลายการแสดงออก

เพื่อให้เข้าใจถึงวิธีแก้ปัญหาของอาจารย์ได้ดีขึ้นง่ายที่สุดในการแทนที่โอเปอเรเตอร์บูลีนด้วย "โทเค็นทางเลือก" ที่เทียบเท่าซึ่งเปลี่ยนให้เป็น redable (imho) ที่ดีกว่าและรหัส C ++ เทียบเท่าทั้งหมด: การใช้ และ 'และ' สำหรับ '&' คุณจะได้รับ

    (not a and not b) != c

น่าเสียดายที่ไม่มีexclusive_orตัวดำเนินการเชิงตรรกะนอกเหนือไปจากnot_eqนี้ซึ่งไม่เป็นประโยชน์ในกรณีนี้

หากเราทำลายการแสดงออกของภาษาธรรมชาติ:

ทั้ง a และ b เป็นเท็จหรือ c เป็นจริง แต่ไม่ใช่ทั้งสองอย่าง

ก่อนอื่นในประโยคเกี่ยวกับบูลีนข้อเสนอ A และ B:

อาจเป็น A หรือ B แต่ไม่ใช่ทั้งคู่

สิ่งนี้แปลเป็นA != B(เฉพาะสำหรับ booleans ไม่ใช่สำหรับประเภท A และ B ใด ๆ )

จากนั้นข้อเสนอ A คือ

a และ b เป็นเท็จทั้งคู่

ซึ่งสามารถระบุได้เป็น

a เป็นเท็จและ b เป็นเท็จ

ซึ่งแปลเป็น(not a and not b)และในที่สุด

c เป็นจริง

ซึ่งแปลเป็นcเพียง (not a and not b) != cรวมพวกเขาคุณจะได้รับอีกครั้ง

สำหรับคำอธิบายเพิ่มเติมว่าการแสดงออกนี้ทำงานอย่างไรฉันขอเลื่อนตารางความจริงที่คนอื่นให้ไว้ในคำตอบของพวกเขา

คุณผิดทั้งคู่

และถ้าฉันอาจ nitpick: การบ้านเริ่มต้นระบุว่า a, b และ c สามารถเป็นตัวเลขที่ไม่เป็นลบ แต่ไม่ได้ระบุอย่างชัดเจนว่าหากพวกเขาเป็นตัวเลขพวกเขาควรถูก จำกัด ไว้ที่ 0 และ 1 หากตัวเลขใด ๆ ที่เป็น ไม่ใช่ 0 แทนtrueตามธรรมเนียมแล้วรหัสต่อไปนี้จะให้คำตอบที่น่าประหลาดใจ:

    auto c = 2; // "true" in some way
    auto a = 0; // "false"
    auto b = 0; // "false"

    std::cout << ((!a && !b) != c);

// this will output: 1 (!)
// fix by making sure that != compares booleans:

    std::cout << ((!a && !b) != (bool)c);

ดีหวังa, bและcได้รับการประกาศให้เป็นboolซึ่งในกรณีนี้c == 1เป็นที่ถูกต้องแต่รหัสที่เลวร้าย อย่างไรก็ตามนี่คือคำตอบที่ฉันจะเขียน: รหัสของ OP อาจเทียบเท่ากับอาจารย์ แต่มันก็ไม่ดี C ++
Konrad Rudolph

1
@KonradRudolph จากข้อความที่ได้รับมอบหมายของ variables are non-negative numbers or booleanOP: ดังนั้น +1 ถึง @dhavenith จากฉันสำหรับการจับรายละเอียดที่คนอื่น ๆ ส่วนใหญ่พลาดที่นี่ (รวมถึงฉันด้วย)
Frodyne

เยี่ยมมาก ขอบคุณ! แต่คุณสามารถอธิบายวิธีแก้ปัญหาให้ศาสตราจารย์ของฉันให้ฉันฟังได้ไหมเพราะฉันไม่เข้าใจ
limonade

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

2

ฉันจะพยายามอธิบายด้วยคำเพิ่มเติม: ตัวเลขสามารถแปลงเป็นค่าบูลีนโดยปริยาย:

ค่าศูนย์ (สำหรับอินทิกรัลจุดลอยตัวและการแจกแจงแบบไม่มีขอบเขต) และตัวชี้โมฆะและค่าตัวชี้ไปยังสมาชิกตัวชี้โมฆะกลายเป็นเท็จ ค่าอื่น ๆ ทั้งหมดกลายเป็นจริง

แหล่งที่มาของ cppreference

สิ่งนี้นำไปสู่ข้อสรุปดังต่อไปนี้:

  • a == 0เป็นเช่นเดียว!aเพราะจะถูกแปลงเป็นบูลีนและคว่ำแล้วซึ่งเท่ากับa !(a != 0)เช่นเดียวกันสำหรับ b

  • c==1จะกลายเป็นความจริงเฉพาะเมื่อc มีค่าเท่ากับ 1 ใช้การแปลง(bool)cจะให้ผลผลิตtrueเมื่อไม่ได้เป็นเพียงถ้าc != 0 c == 1ดังนั้นจึงสามารถใช้งานได้เพราะมักใช้ค่า 1 เพื่อเป็นตัวแทนtrueแต่ไม่รับประกัน

  • a != bเป็นเช่นเดียวกับa xor bเวลาaและbนิพจน์บูลีน เป็นจริงเมื่อค่าหนึ่งหรืออีกค่าเป็นจริง แต่ไม่ใช่ทั้งสองอย่าง ในกรณีนี้ทางด้านซ้ายมือ(a==0 && b==0)เป็นบูลีนดังนั้นทางด้านขวาcจะถูกแปลงเป็นบูลีนด้วยเช่นกันดังนั้นทั้งสองฝ่ายจะตีความว่าเป็นการแสดงออกทางบูลีนดังนั้นจึง!=เป็นเช่นเดียวกับxorในกรณีนี้

คุณสามารถตรวจสอบทั้งหมดนี้ด้วยตัวคุณเองด้วยความจริงที่ว่าคำตอบอื่น ๆ ที่ให้ไว้


2

อย่างที่เราเห็นจากตารางความจริง:

  • !( not) และ==0ให้ผลลัพธ์เดียวกัน
  • !=และxorให้ผลลัพธ์เดียวกัน
  • c==1 เหมือนกันเพียงแค่ c

หนึ่งอันใต้อีกอันแสดงให้เห็นว่าเหตุใดนิพจน์ทั้งสองนี้ให้ผลลัพธ์เหมือนกัน:

(a==0 && b==0) xor (c==1)
(!a   && !b)   !=   c

ตารางความจริง:

ไม่

    |   | ! |
    | 0 | 1 |
    | 1 | 0 |

== 0

    |   |==0|
    | 0 | 1 |
    | 1 | 0 |

== 1

    |   |==1|
    | 0 | 0 |
    | 1 | 1 |

และ

   | a | b | && |
   | 0 | 0 |  0 |
   | 0 | 1 |  0 |
   | 1 | 0 |  0 |
   | 1 | 1 |  1 |

ไม่เท่ากับ

   | a | b | != |
   | 0 | 0 |  0 |
   | 0 | 1 |  1 |
   | 1 | 0 |  1 |
   | 1 | 1 |  0 |

แฮคเกอร์

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