ทำไม 0 จึงเป็นเท็จ


115

คำถามนี้อาจฟังดูเป็นใบ้ แต่ทำไม0ประเมินfalseและค่าอื่น ๆ [จำนวนเต็ม] trueเป็นภาษาโปรแกรมส่วนใหญ่

การเปรียบเทียบสตริง

เนื่องจากคำถามดูเหมือนจะง่ายเกินไปฉันจะอธิบายตัวเองมากกว่านี้ก่อนอื่นอาจเห็นได้ชัดจากโปรแกรมเมอร์ทุกคน แต่ทำไมไม่มีภาษาการเขียนโปรแกรม - อาจมี แต่ไม่มี ฉันใช้ - ซึ่งเป็น0ค่าที่ประเมินtrueและ [จำนวนเต็ม] อื่น ๆ เพื่อfalseที่ไหน คำพูดหนึ่งอาจดูสุ่ม แต่ฉันมีตัวอย่างเล็ก ๆ น้อย ๆ ที่มันอาจเป็นความคิดที่ดี ก่อนอื่นเราลองมาดูตัวอย่างของการเปรียบเทียบสามสายผมจะเอา C มาstrcmpเป็นตัวอย่าง: โปรแกรมเมอร์ที่ลอง C เป็นภาษาแรกของเขาอาจถูกล่อลวงให้เขียนโค้ดต่อไปนี้:

if (strcmp(str1, str2)) { // Do something... }

เนื่องจากstrcmpส่งคืน0ซึ่งประเมินว่าfalseเมื่อใดที่สตริงมีค่าเท่ากันสิ่งที่โปรแกรมเมอร์เริ่มต้นพยายามทำล้มเหลวอย่างน่าสังเวชและโดยทั่วไปเขาไม่เข้าใจว่าทำไมในตอนแรก มีการ0ประเมินผลtrueแทนฟังก์ชันนี้สามารถใช้ในการแสดงออกที่ง่ายที่สุด - อย่างใดอย่างหนึ่งข้างต้น - เมื่อเปรียบเทียบกับความเสมอภาคและการตรวจสอบที่เหมาะสมสำหรับ-1และ1จะทำได้เมื่อจำเป็นเท่านั้น เราจะพิจารณาประเภทการคืนเป็นbool(ในความคิดของเราฉันหมายถึง) ส่วนใหญ่เวลา

นอกจากนี้ขอแนะนำชนิดใหม่signที่ใช้เวลาเพียงค่า-1, และ0 1ที่สามารถมีประโยชน์สวย ลองนึกภาพว่ามีโอเปอเรเตอร์ยานอวกาศใน C ++ และเราต้องการมันstd::string(ดีมีcompareฟังก์ชั่นอยู่แล้ว แต่โอเปอเรเตอร์ยานอวกาศสนุกกว่า) การประกาศจะเป็นดังต่อไปนี้:

sign operator<=>(const std::string& lhs, const std::string& rhs);

ได้0รับการประเมินtrueแล้วผู้ประกอบการยานอวกาศจะไม่มีอยู่จริงและเราอาจประกาศอย่างoperator==นั้นได้:

sign operator==(const std::string& lhs, const std::string& rhs);

สิ่งนี้operator==จะมีการจัดการเปรียบเทียบสามทางในคราวเดียวและยังสามารถใช้เพื่อทำการตรวจสอบต่อไปนี้ในขณะที่ยังสามารถตรวจสอบว่าสตริงใดที่เป็น lexicographically

if (str1 == str2) { // Do something... }

การจัดการข้อผิดพลาดเก่า

ตอนนี้เรามีข้อยกเว้นดังนั้นส่วนนี้ใช้เฉพาะกับภาษาเก่าที่ไม่มีสิ่งนั้นอยู่ (ตัวอย่างเช่น C) ถ้าเราดูไลบรารี่มาตรฐานของ C (และ POSIX อันเดียวกัน) เราจะเห็นได้ว่าฟังก์ชั่น maaaaany จะกลับมาอีก0ครั้งเมื่อประสบความสำเร็จและจำนวนเต็มอื่น ๆ ฉันได้เห็นบางคนทำสิ่งนี้:

#define TRUE 0
// ...
if (some_function() == TRUE)
{
    // Here, TRUE would mean success...
    // Do something
}

หากเราคิดเกี่ยวกับวิธีคิดในการเขียนโปรแกรมเรามักจะมีรูปแบบการให้เหตุผลต่อไปนี้:

Do something
Did it work?
Yes ->
    That's ok, one case to handle
No ->
    Why? Many cases to handle

ถ้าเราคิดเกี่ยวกับมันอีกครั้งก็จะได้ทำให้ความรู้สึกที่จะใส่เฉพาะค่าเป็นกลาง0เพื่อyes(และนั่นคือวิธีการทำงานของ C ทำงาน) ในขณะที่ค่าอื่น ๆ noทุกคนสามารถจะมีการแก้หลายกรณีของ อย่างไรก็ตามในทุกภาษาโปรแกรมที่ผมรู้ว่า (อาจจะยกเว้นบางภาษา esotheric ทดลอง) ที่yesประเมินfalseในifสภาพในขณะที่ทุกกรณีที่จะประเมินno trueมีหลายสถานการณ์เมื่อ "ทำงาน" หมายถึงหนึ่งกรณีขณะที่ "ไม่ทำงาน" หมายถึงสาเหตุที่เป็นไปได้มากมาย ถ้าเราคิดแบบนั้นการ0ประเมินtrueและส่วนที่เหลือfalseจะทำให้เข้าใจได้มากกว่า

ข้อสรุป

ข้อสรุปของฉันคือคำถามดั้งเดิมของฉัน: ทำไมเราจึงออกแบบภาษาที่0เป็นfalseและค่าอื่น ๆtrueโดยคำนึงถึงตัวอย่างของฉันด้านบนและอาจจะมากกว่าฉันไม่ได้คิด?

การติดตามผล:เป็นเรื่องดีที่ได้เห็นว่ามีคำตอบมากมายเกี่ยวกับความคิดมากมายและเหตุผลที่เป็นไปได้ที่จะเป็นเช่นนั้น ฉันรักความหลงใหลที่คุณมีต่อมัน ฉันเริ่มถามคำถามนี้ด้วยความเบื่อ แต่เนื่องจากคุณดูน่าหลงใหลมากฉันเลยตัดสินใจเพิ่มอีกซักนิดและถามถึงเหตุผลเบื้องหลังตัวเลือก Boolean สำหรับ 0 และ 1ใน Math.SE :)


32
strcmp()ไม่ใช่ตัวอย่างที่ดีสำหรับจริงหรือเท็จเนื่องจากมันคืนค่าที่แตกต่างกัน 3 ค่า และคุณจะประหลาดใจเมื่อคุณเริ่มใช้เชลล์โดยที่ 0 หมายถึงจริงและสิ่งอื่นใดที่เป็นเท็จ
ott--

52
@ ott--: ใน Unix shells, 0 หมายถึงความสำเร็จและไม่เป็นศูนย์หมายถึงความล้มเหลว - ไม่ใช่สิ่งเดียวกับ "true" และ "false"
Keith Thompson

14
@ KeithThompson: ใน Bash (และกระสุนอื่น ๆ ) "ความสำเร็จ" และ "ความล้มเหลว" จริงๆจะเหมือนกับ "จริง" และ "เท็จ" พิจารณาตัวอย่างเช่นคำสั่งif true ; then ... ; fiที่trueเป็นคำสั่งที่ส่งกลับศูนย์นี้และบอกว่าจะเรียกใช้if ...
ruakh

13
ไม่มีบูลีนในฮาร์ดแวร์ใด ๆ เพียงแค่เลขฐานสองและในประวัติศาสตร์ ISAs ส่วนใหญ่ตัวเลขที่ไม่เป็นศูนย์จะถูกพิจารณาว่าเป็น "จริง" ในคำแนะนำการแยกย่อยตามเงื่อนไขทั้งหมด (เว้นแต่ว่าพวกเขากำลังใช้แฟล็กแทน) ดังนั้นภาษาระดับต่ำจึงจำเป็นต้องทำตามคุณสมบัติฮาร์ดแวร์พื้นฐาน
SK-logic

2
@MasonWheeler มีประเภทบูลีนไม่ได้หมายความว่าอะไร ยกตัวอย่างเช่นงูหลามจะมีboolประเภท แต่เปรียบเทียบ / ถ้าเงื่อนไขอื่น ๆ สามารถมีค่าตอบแทนใด ๆ
Bakuriu

คำตอบ:


98

0เป็นfalseเพราะพวกเขาทั้งสององค์ประกอบเป็นศูนย์ในการร่วมกันsemirings แม้ว่าพวกเขาจะเป็นประเภทข้อมูลที่แตกต่างกัน แต่มันก็เป็นเรื่องที่เข้าใจได้ง่ายที่จะทำการแปลงระหว่างพวกมัน

  • 0เป็นตัวตนของการเพิ่มและศูนย์สำหรับการคูณ นี้เป็นจริงสำหรับจำนวนเต็มและ rationals แต่ไม่ IEEE-754 จำนวนจุดลอยตัว: และ0.0 * NaN = NaN0.0 * Infinity = NaN

  • falseคือตัวตนของ Boolean xor (⊻) และศูนย์สำหรับ Boolean และ (∧) หาก Booleans แสดงเป็น {0, 1} - ชุดของจำนวนเต็มโมดูโล 2 - คุณสามารถคิดถึง⊻เป็นส่วนเสริมได้โดยไม่ต้องมีการดำเนินการและ∧เป็นการคูณ

  • ""และ[]เป็นเอกลักษณ์ของการต่อข้อมูล แต่มีการดำเนินการหลายอย่างที่ทำให้รู้สึกเป็นศูนย์ การทำซ้ำเป็นหนึ่งเดียว แต่การทำซ้ำและการต่อข้อมูลไม่ได้แจกจ่ายดังนั้นการดำเนินการเหล่านี้จึงไม่ก่อให้เกิด semiring

การแปลงโดยนัยดังกล่าวมีประโยชน์ในโปรแกรมขนาดเล็ก แต่ในโปรแกรมขนาดใหญ่อาจทำให้โปรแกรมยากขึ้นที่จะให้เหตุผล หนึ่งในข้อตกลงด้านการออกแบบภาษา


1
ยินดีที่คุณพูดถึงรายการ (BTW nilเป็นทั้งรายการที่ว่างเปล่า[]และfalseค่าใน Common LISP มีแนวโน้มที่จะผสานข้อมูลประจำตัวจากประเภทข้อมูลที่แตกต่างกันหรือไม่) คุณยังต้องอธิบายว่าทำไมจึงเป็นเรื่องธรรมดาที่จะต้องพิจารณาว่าเป็นตัวตนเพิ่มเติม ไม่ใช่วิธีอื่น ๆ เป็นไปไม่ได้ที่จะต้องพิจารณาtrueในขณะที่ระบุสำหรับANDและศูนย์OR?
Giorgio

3
+1 สำหรับการอ้างอิงถึงตัวตนที่คล้ายกัน ในที่สุดคำตอบที่ไม่เพียง แต่จะทำให้ "การประชุมจัดการกับมัน"
l0b0

5
+1 สำหรับการให้รายละเอียดของรูปธรรมและคณิตศาสตร์ที่เก่าแก่มากซึ่งสิ่งนี้ได้รับการติดตามและใช้เวลานาน
จิมมี่ฮอฟฟา

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

1
@TonioElGringo: ความแตกต่างระหว่างจริงและเท็จคือความแตกต่างระหว่าง XOR และ XNOR เราสามารถสร้างวงแหวน isomorphic ได้โดยใช้ AND / XOR โดยที่จริงคือตัวตนแบบหลายค่าและเป็นเท็จของสารเติมแต่งหรือด้วย OR และ XNOR โดยที่ false คือตัวบ่งชี้แบบหลายค่าและความจริงคือสารเติมแต่ง การดำเนินงานขั้นพื้นฐานอย่างที่ XOR เป็น
supercat

74

เพราะคณิตศาสตร์ใช้งานได้

FALSE OR TRUE is TRUE, because 0 | 1 is 1.

... insert many other examples here.

ตามเนื้อผ้าโปรแกรม C มีเงื่อนไขเช่น

if (someFunctionReturningANumber())

ค่อนข้างมากกว่า

if (someFunctionReturningANumber() != 0)

เพราะแนวคิดของศูนย์ที่เทียบเท่ากับเท็จนั้นเป็นที่เข้าใจกันดี


21
ภาษาได้รับการออกแบบเช่นนั้นเพราะคณิตศาสตร์เหมาะสม นั่นมาก่อน
Robert Harvey

26
@ Morwenn มันย้อนกลับไปในศตวรรษที่ 19 และ George Boole ผู้คนเป็นตัวแทนของ False เป็น 0 และ True as! 0 เป็นเวลานานกว่าคอมพิวเตอร์
Charles E. Grant

11
ฉันไม่เห็นว่าทำไมคณิตศาสตร์ไม่ทำงานอย่างอื่นถ้าคุณเพียงแค่เปลี่ยนคำจำกัดความทั้งหมดเพื่อให้ AND เป็น + และ OR เป็น *
Neil G

7
แน่นอน: คณิตศาสตร์ทำงานได้ทั้งสองทางและคำตอบสำหรับคำถามนี้ดูเหมือนว่าเป็นเรื่องธรรมดา
Neil G

6
@ Robert มันจะดีถ้าคุณสามารถสะกด "การขีดทางคณิตศาสตร์" ในโพสต์ของคุณ
phant0m

38

อย่างที่คนอื่นพูดคณิตศาสตร์มาก่อน นี่คือเหตุผลที่ 0 falseและ true1

เรากำลังพูดถึงคณิตศาสตร์อะไร Boolean algebrasซึ่งมีอายุตั้งแต่กลางปี ​​1800 ก่อนที่จะมีคอมพิวเตอร์ดิจิทัลเข้ามา

คุณสามารถพูดได้ว่าการประชุมออกมาจากตรรกะเชิงประพจน์ซึ่งยังเก่ากว่าพีชคณิตแบบบูล นี่คือการทำให้เป็นรูปธรรมของผลลัพธ์เชิงตรรกะจำนวนมากที่โปรแกรมเมอร์รู้จักและชื่นชอบ ( false || xเท่ากับx, true && xเท่ากับxและอื่น ๆ )

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


2
คุณทำได้แน่นอน แต่ทำให้มันเป็น "มาตรฐาน" ที่เข้ากันได้ดีกับคณิตศาสตร์ทั่วไป (0 + 1 = 1 ไม่ใช่ 0 + 1 = 0)
joshin4colours

2
ใช่ แต่คุณน่าจะเขียน AND ด้วย + และ OR ด้วย * ถ้าคุณกลับคำจำกัดความเช่นกัน
Neil G

3
คณิตศาสตร์ไม่ได้มาก่อน คณิตศาสตร์ยอมรับว่า 0 และ 1 จัดรูปแบบฟิลด์ซึ่ง AND เป็นเหมือนการคูณและ OR เหมือนกับการเพิ่ม
Kaz

1
@Kaz: แต่ {0, 1} ที่มี OR และ AND ไม่ได้สร้างฟิลด์
Giorgio

2
มันรบกวนจิตใจผมเล็ก ๆ น้อย ๆ true = 1ว่าคำตอบมากขึ้นและความเห็นบอกว่า นั่นไม่ได้ค่อนข้างแน่นอนเพราะtrue != 0ซึ่งไม่เหมือนกัน เหตุผลหนึ่ง (ไม่เพียงหนึ่ง) if(something == true) { ... }เหตุผลที่ควรหลีกเลี่ยงการเปรียบเทียบเช่น
JensG

26

ฉันคิดว่าสิ่งนี้เกี่ยวข้องกับ "การสืบทอด" จากอุปกรณ์อิเล็กทรอนิกส์และพีชคณิตแบบบูลที่

  • 0= off, negative, no,false
  • 1= on, positive, yes,true

strcmpส่งคืนค่า 0 เมื่อสตริงมีค่าเท่ากันเกี่ยวข้องกับการนำไปใช้จริงเนื่องจากสิ่งที่มันทำจริง ๆ คือการคำนวณ "ระยะทาง" ระหว่างสองสตริง การที่ 0 ถือว่าเป็นเท็จนั้นเป็นเรื่องบังเอิญ

กลับ 0เมื่อประสบความสำเร็จทำให้รู้สึกเพราะ 0 ในกรณีนี้ใช้เพื่อหมายถึงไม่มีข้อผิดพลาดและหมายเลขอื่นใดจะเป็นรหัสข้อผิดพลาด การใช้หมายเลขอื่นเพื่อความสำเร็จจะไม่สมเหตุสมผลเนื่องจากคุณมีรหัสความสำเร็จเพียงรหัสเดียวในขณะที่คุณสามารถมีรหัสข้อผิดพลาดหลายรหัสได้ คุณใช้ "ใช้งานได้หรือไม่" เป็นถ้าคำสั่งแสดงออกและพูด 0 = ใช่จะทำให้รู้สึกมากขึ้น แต่การแสดงออกที่ถูกต้องมากขึ้น "มีอะไรผิดพลาด?" แล้วคุณจะเห็นว่า 0 = ไม่มีเหตุผล ความคิดของการไม่ได้ทำให้รู้สึกจริงๆที่นี่เป็นก็จริงfalse/trueno error code/error code


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

1
อันที่จริงผมว่า0สำหรับsuccess/no errorเป็นสิ่งเดียวที่ทำให้รู้สึกเมื่อจำนวนเต็มอื่น ๆ แทนรหัสข้อผิดพลาด ที่0ยังเกิดขึ้นเพื่อเป็นตัวแทนfalseในกรณีอื่น ๆ ไม่ได้เรื่องจริงๆเนื่องจากเราไม่ได้พูดถึงจริงหรือเท็จนี่เลย;)
Svish

ฉันมีความคิดเดียวกันดังนั้นฉัน upped
user60812

1
จุดของคุณเกี่ยวกับการstrcmp()คำนวณระยะทางค่อนข้างดี ถ้ามันถูกเรียกstrdiff()แล้วก็if (!strdiff())จะมีเหตุผลมาก
Kevin Cox

"electronics [... ] โดยที่ 0 = [... ] false, 1 = [... ] จริง" - แม้ในอุปกรณ์อิเล็กทรอนิกส์นี่เป็นเพียงการประชุมและไม่ใช่เพียงข้อตกลงเดียว เราเรียกตรรกะเชิงบวกนี้ว่า แต่คุณสามารถใช้ตรรกะเชิงลบได้โดยที่แรงดันบวกหมายถึงเท็จและลบนั้นบ่งชี้ว่าเป็นจริง จากนั้นวงจรที่คุณใช้สำหรับและกลายเป็น OR หรือกลายเป็น AND และอื่น ๆ เนื่องจากกฎหมายของเดอมอร์แกนทุกอย่างเท่าเทียมกัน บางครั้งคุณจะพบส่วนหนึ่งของวงจรอิเล็กทรอนิกส์ที่นำมาใช้ในตรรกะเชิงลบเพื่อความสะดวกที่จุดของชื่อของสัญญาณในส่วนนั้นจะถูกบันทึกไว้ด้วยแถบเหนือพวกเขา
จูลส์

18

ตามที่อธิบายไว้ในบทความนี้ค่าfalseและtrueไม่ควรสับสนกับจำนวนเต็ม 0 และ 1 แต่อาจถูกระบุด้วยองค์ประกอบของเขต Galois (เขต จำกัด ) ของสององค์ประกอบ (ดูที่นี่ )

เขตข้อมูลเป็นชุดที่มีสองการดำเนินการที่ตอบสนองความจริงบางอย่าง

สัญลักษณ์ 0 และ 1 ใช้เพื่อแสดงอัตลักษณ์การบวกและการคูณของฟิลด์ตามอัตภาพเนื่องจากจำนวนจริงเป็นฟิลด์ (แต่ไม่ใช่ จำกัด แน่นอน) ซึ่งมีเอกลักษณ์เป็นตัวเลข 0 และ 1

ตัวตนเพิ่มเติมคือองค์ประกอบ 0 ของสนามเช่นนั้นสำหรับทุก x:

x + 0 = 0 + x = x

และเอกลักษณ์การคูณคือองค์ประกอบ 1 ของสนามเช่นนั้นสำหรับ x ทั้งหมด:

x * 1 = 1 * x = x

เขตข้อมูลอัน จำกัด ของสององค์ประกอบมีเพียงสององค์ประกอบเท่านั้นนั่นคือตัวระบุเพิ่มเติม 0 (หรือfalse) และตัวบ่งชี้การคูณ 1 (หรือtrue) การดำเนินการสองอย่างของฟิลด์นี้คือโลจิคัล XOR (+) และโลจิคัล AND (*)

บันทึก. หากคุณพลิกการดำเนินการ (XOR คือการคูณและ AND เป็นการบวก) การคูณจะไม่กระจายมากกว่าการเติมและคุณไม่มีฟิลด์อีกต่อไป ในกรณีเช่นนี้คุณไม่มีเหตุผลที่จะเรียกสององค์ประกอบ 0 และ 1 (ในลำดับใด ๆ ) โปรดทราบว่าคุณไม่สามารถเลือกการดำเนินการหรือแทน XOR: ไม่ว่าคุณจะตีความว่า OR / และเป็นการเพิ่ม / การคูณโครงสร้างผลลัพธ์ไม่ใช่เขตข้อมูล

เกี่ยวกับฟังก์ชั่น C:

  • ฟังก์ชั่นจำนวนมากกลับจำนวนเต็มที่เป็นรหัสข้อผิดพลาด 0 หมายถึงไม่มีข้อผิดพลาด
  • ฟังก์ชั่นstrcmpคำนวณความแตกต่างระหว่างสองสตริง 0 หมายความว่าไม่มีความแตกต่างระหว่างสองสายคือนั่นคือสองสายมีค่าเท่ากัน

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


1
+1 สำหรับการแสดงว่าหากคุณสลับเหล่านี้โดยพลการคณิตศาสตร์จะไม่ทำงานอีกต่อไป
Jimmy Hoffa

2
พลิกแล้ว: เมื่อกำหนดเขตข้อมูลที่มีสององค์ประกอบและการดำเนินงาน * และ + เราจะระบุ True ด้วย 0 และ False ด้วย 1 เราระบุ OR ด้วย * และ XOR ด้วย +
Neil G

1
คุณจะพบว่าการระบุทั้งสองนี้เสร็จสิ้นในฟิลด์เดียวกันและทั้งสองนั้นสอดคล้องกับกฎของตรรกะบูลีน น่าเสียดายที่โน้ตของคุณไม่ถูกต้อง :)
Neil G

1
หากคุณสมมติว่า True = 0 และ XOR เป็น + ดังนั้น True ต้องเป็นตัวตนของ XOR แต่ไม่ใช่เพราะ True XOR True = False นอกจากว่าคุณจะกำหนดการดำเนินการ XOR บน True อีกครั้งดังนั้น True XOR True = True แน่นอนว่างานก่อสร้างของคุณเพราะคุณเพิ่งเปลี่ยนชื่อสิ่งต่าง ๆ (ในโครงสร้างทางคณิตศาสตร์ใด ๆ คุณสามารถทำการเปลี่ยนชื่อและรับโครงสร้าง isomorphic ได้เสมอ) ในทางกลับกันถ้าคุณให้ True, False และ XOR มีความหมายตามปกติ True XOR True = False และ True ไม่สามารถเป็นตัวตนเพิ่มเติมได้เช่น True ไม่สามารถเป็น 0
Giorgio

1
@Giorgio: ฉันแก้ไขการก่อสร้างของฉันตามความคิดเห็นของคุณในความคิดเห็นสุดท้ายของฉัน ...
Neil G

13

คุณควรพิจารณาว่าระบบทางเลือกสามารถตัดสินใจออกแบบได้

Shells: 0 สถานะทางออกเป็นจริงไม่ใช่ศูนย์เป็นเท็จ

ตัวอย่างของเปลือกหอยที่รักษาสถานะ 0 ออกตามจริงได้ถูกกล่าวถึงแล้ว

$ ( exit 0 ) && echo "0 is true" || echo "0 is false"
0 is true
$ ( exit 1 ) && echo "1 is true" || echo "1 is false"
1 is false

เหตุผลมีว่ามีวิธีหนึ่งที่จะประสบความสำเร็จ แต่หลายวิธีที่จะล้มเหลวดังนั้นการใช้ 0 เป็นค่าพิเศษหมายถึง "ไม่มีข้อผิดพลาด" เป็นจริง

Ruby: 0 ก็เหมือนกับหมายเลขอื่น ๆ

ในบรรดาภาษาการเขียนโปรแกรม "ปกติ" มีค่าผิดปกติบางอย่างเช่น Ruby ซึ่งถือว่า 0 เป็นค่าจริง

$ irb
irb(main):001:0> 0 ? '0 is true' : '0 is false'
=> "0 is true"

เหตุผลก็คือว่าเพียงfalseและnilควรเป็นเท็จ สำหรับผู้เริ่มหัดทับทิมหลายคนมันเป็น gotcha อย่างไรก็ตามในบางกรณีก็ดีที่ 0 ได้รับการปฏิบัติเช่นเดียวกับหมายเลขอื่น ๆ

irb(main):002:0> (pos = 'axe' =~ /x/) ? "Found x at position #{pos}" : "x not found"
=> "Found x at position 1"
irb(main):003:0> (pos = 'xyz' =~ /x/) ? "Found x at position #{pos}" : "x not found"
=> "Found x at position 0"
irb(main):004:0> (pos = 'abc' =~ /x/) ? "Found x at position #{pos}" : "x not found"
=> "x not found"

อย่างไรก็ตามระบบดังกล่าวทำงานในภาษาที่สามารถแยกแยะบูลีนเป็นประเภทที่แยกต่างหากจากตัวเลข ในวันก่อนหน้าของการคำนวณโปรแกรมเมอร์ที่ทำงานกับภาษาแอสเซมบลีหรือภาษาเครื่องดิบไม่มีความฟุ่มเฟือยเช่นนั้น อาจเป็นธรรมดาที่จะถือว่า 0 เป็นสถานะ "blank" และตั้งค่าบิตเป็น 1 เป็นแฟล็กเมื่อโค้ดตรวจพบว่ามีบางอย่างเกิดขึ้น โดยการขยายอนุสัญญาที่พัฒนาว่าศูนย์ได้รับการปฏิบัติเป็นเท็จและค่าที่ไม่เป็นศูนย์จะถือว่าเป็นจริง อย่างไรก็ตามมันไม่จำเป็นต้องเป็นอย่างนั้น

Java: ตัวเลขไม่สามารถถือว่าเป็นบูลีนเลย

ใน Java trueและfalseเป็นค่าบูลีนเท่านั้น ตัวเลขไม่ใช่บูลีนและไม่สามารถถูกแบ่งเป็นบูลีน ( Java Language Specification, Sec 4.2.2 ):

booleanมีบรรยากาศระหว่างชนิดหนึ่งและชนิดไม่มี

กฎนั้นเพียงแค่หลีกเลี่ยงคำถามทั้งหมด - นิพจน์บูลีนทั้งหมดต้องถูกเขียนลงในโค้ดอย่างชัดเจน


1
Rebol และ Redทั้งคู่ปฏิบัติต่อ INTEGER ที่มีค่า 0! ค่าเป็นจริงและมี NONE แยกต่างหาก! ประเภท (มีเพียงค่าเดียวไม่มี) ถือว่าเป็นเท็จเงื่อนไขนอกเหนือไปจาก LOGIC! เท็จ ฉันพบความยุ่งยากในการพยายามเขียนโค้ด JavaScript ที่ถือว่า 0 เป็นเท็จ มันเป็นการตัดสินใจที่ไม่น่าเชื่อสำหรับภาษาที่พิมพ์แบบไดนามิก หากคุณต้องการทดสอบบางสิ่งที่อาจเป็นโมฆะหรือ 0 คุณต้องเลิกเขียนif (thing === 0)นั่นไม่ใช่เรื่องเจ๋ง
HostileFork

@HostileFork ฉันไม่รู้ ผมพบว่ามันทำให้รู้สึกว่า0เป็นtrue(ตามที่ทุกจำนวนเต็มอื่น ๆ ) ในภาษาแบบไดนามิก บางครั้งฉันก็จับได้0เมื่อพยายามจับNoneงูใหญ่และบางครั้งก็ยากที่จะสังเกตเห็น
Morwenn

2
ทับทิมไม่ใช่ค่าผิดปกติ Ruby นำสิ่งนี้มาจาก Lisp (Ruby เรียกอย่างลับ ๆ ว่า "MatzLisp") เสียงกระเพื่อมเป็นภาษาหลักในวิทยาการคอมพิวเตอร์ ศูนย์ยังเป็นเพียงมูลค่าที่แท้จริงใน POSIX if [ 0 ] ; then echo this executes ; fiเปลือกเพราะมันเป็นชิ้นส่วนของข้อความ: ค่าข้อมูลเท็จคือสตริงว่างและเท็จที่ทดสอบได้เป็นสถานะการเลิกจ้างที่ล้มเหลวของคำสั่งซึ่งจะแสดงโดยที่ไม่ใช่ศูนย์
Kaz

8

ก่อนพูดถึงกรณีทั่วไปเราสามารถพูดคุยตัวอย่างเคาน์เตอร์ของคุณ

การเปรียบเทียบสตริง

ในความเป็นจริงก็มีเหมือนกัน การเปรียบเทียบดังกล่าวคำนวณระยะห่างระหว่างวัตถุทั้งสอง เมื่อวัตถุเท่ากันระยะทางจะน้อยที่สุด ดังนั้นเมื่อ "เปรียบเทียบประสบความสำเร็จ" มีค่าเป็น 0 แต่จริงๆค่าตอบแทนของstrcmpคือไม่if (strcmp(...)) do_when_equal() else do_when_not_equal()บูลก็คือระยะทางและว่าสิ่งที่ดักโปรแกรมเมอร์ไม่รู้ทำ

ใน C ++ เราสามารถออกแบบใหม่strcmpเพื่อส่งคืนDistanceออบเจ็กต์ซึ่งจะแทนที่operator bool()จริงเมื่อ 0 (แต่คุณจะถูกกัดด้วยปัญหาชุดอื่น) หรือใน C ธรรมดามีstreqฟังก์ชันที่ส่งกลับ 1 เมื่อสตริงมีค่าเท่ากันและ 0 เป็นอย่างอื่น

การเรียก API / รหัสออกจากโปรแกรม

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

กรณีทั่วไป

สิ่งนี้ทำให้เรามีคำถาม: ทำไมค่าบูลีนTrueและFalseแสดงโดยทั่วไปด้วย 1 และ 0 ตามลำดับคืออะไร

นอกจากเรื่องอัตนัย "มันรู้สึกดีกว่าวิธีนี้" การโต้เถียงนี่คือเหตุผลบางอย่าง (ส่วนตัวเช่นกัน) ฉันสามารถคิด:

  • การเปรียบเทียบวงจรไฟฟ้า กระแสไฟฟ้าเปิดเป็น 1 วินาทีและปิดเป็น 0 วินาที ฉันชอบที่จะมี (1, ใช่, จริง, เปิด) ด้วยกันและ (0, ไม่, เท็จ, ปิด) แทนที่จะผสมกัน

  • การเริ่มต้นหน่วยความจำ เมื่อฉันmemset(0)หลายตัวแปร (ไม่ว่าจะเป็น ints, ลอย, bools) ฉันต้องการค่าของพวกเขาเพื่อให้ตรงกับสมมติฐานที่อนุรักษ์นิยมมากที่สุด เช่นผลรวมของฉันเริ่มต้นที่ 0 ภาคแสดงเป็นเท็จเป็นต้น

บางทีเหตุผลเหล่านี้ทั้งหมดอาจเชื่อมโยงกับการศึกษาของฉัน - ถ้าฉันได้รับการสอนให้เชื่อมโยง 0 กับ True ตั้งแต่ต้นฉันจะไปทางอื่น


2
จริงๆแล้วมีอย่างน้อยหนึ่งภาษาการเขียนโปรแกรมที่ถือว่า 0 เป็นจริง เปลือกยูนิกซ์
Jan Hudec

+1 สำหรับการแก้ไขปัญหาจริง: คำถามส่วนใหญ่ของ Morwenn ไม่เกี่ยวกับboolเลย
dan04

@ dan04 มันคือ โพสต์ทั้งหมดเป็นเรื่องเกี่ยวกับเหตุผลที่อยู่เบื้องหลังทางเลือกของการโยนจากintไปboolในหลายภาษาโปรแกรม สิ่งที่เปรียบเทียบและแสดงข้อผิดพลาดเป็นเพียงตัวอย่างของสถ
Morwenn

6

จากมุมมองระดับสูงคุณกำลังพูดถึงประเภทข้อมูลที่แตกต่างกันสามประเภท:

  1. บูลีน การประชุมเชิงคณิตศาสตร์ในพีชคณิตบูลีนคือการใช้ 0 สำหรับfalseและ 1 สำหรับtrueดังนั้นจึงเหมาะสมที่จะปฏิบัติตามอนุสัญญานั้น ฉันคิดว่าวิธีนี้ทำให้รู้สึกง่ายขึ้น

  2. ผลการเปรียบเทียบ นี้มีสามค่า: <, =และ>(สังเกตว่าไม่มีของพวกเขาเป็นtrue) สำหรับพวกเขามันสมเหตุสมผลที่จะใช้ค่า -1, 0 และ 1 ตามลำดับ (หรือโดยทั่วไปแล้วค่าลบศูนย์และค่าบวก)

    strcmp(str1, str2) == 0หากคุณต้องการที่จะตรวจสอบเพื่อความเท่าเทียมกันและคุณมีเพียงฟังก์ชั่นที่มีประสิทธิภาพการเปรียบเทียบทั่วไปผมคิดว่าคุณควรจะทำให้มันชัดเจนโดยใช้สิ่งที่ต้องการ ฉันพบว่าการใช้!ในสถานการณ์นี้ทำให้เกิดความสับสนเพราะมันปฏิบัติต่อค่าที่ไม่ใช่แบบบูลราวกับว่ามันเป็นบูลีน

    นอกจากนี้โปรดทราบว่าการเปรียบเทียบและความเท่าเทียมกันไม่จำเป็นต้องเหมือนกัน ตัวอย่างเช่นถ้าคุณสั่งคนตามวันเกิดของพวกเขา, Compare(me, myTwin)ควรกลับ0แต่ควรกลับEquals(me, myTwin)false

  3. ความสำเร็จหรือความล้มเหลวของฟังก์ชันอาจมีรายละเอียดเกี่ยวกับความสำเร็จหรือความล้มเหลวนั้น หากคุณกำลังพูดถึง Windows ระบบจะเรียกใช้ประเภทนี้HRESULTและค่าที่ไม่เป็นศูนย์จะไม่บ่งบอกถึงความล้มเหลว ในความเป็นจริงค่าลบหมายถึงความล้มเหลวและความสำเร็จที่ไม่ใช่เชิงลบ ค่าความสำเร็จนั้นบ่อยครั้งมากS_OK = 0แต่ก็สามารถยกตัวอย่างเช่นS_FALSE = 1หรือค่าอื่น ๆ

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

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


4

ศูนย์อาจเป็นเท็จเพราะ CPU ส่วนใหญ่มีค่าสถานะ ZERO ที่สามารถใช้ในการแยกสาขาได้ มันบันทึกการดำเนินการเปรียบเทียบ

ให้ดูว่าทำไม

psuedocode บางอันเนื่องจากผู้ชมอาจไม่ได้อ่านชุดประกอบ

c- source การวนลูปแบบง่าย ๆ wibble 10 ครั้ง

for (int foo =10; foo>0; foo-- ) /* down count loop is shorter */
{  
   wibble();
}

บางคนคิดว่าการชุมนุมทำเช่นนั้น

0x1000 ld a 0x0a      'foo=10
0x1002 call 0x1234    'call wibble()
0x1005 dec a          'foo--
0x1006 jrnz -0x06      'jump back to 0x1000 if not zero
0x1008  

c- แหล่งที่มาอีกอย่างง่าย ๆ เรียกการวนรอบ 10 ครั้ง

for (int foo =0; foo<10; foo-- ) /* up count loop is longer  */
{  
   wibble();
}

บางชุดทำท่าประกอบในกรณีนี้

0x1000 ld a 0x00      'foo=0
0x1002 call 0x1234    'call wibble()
0x1005 dec a          'foo--
0x1006 cmp 0x0a       'compare foo to 10 ( like a subtract but we throw the result away)
0x1008 jrns -0x08      'jump back to 0x1000 if compare was negative
0x100a  

บางแหล่ง c เพิ่มเติม

int foo=10;
if ( foo ) wibble()

และการชุมนุม

0x1000 ld a 0x10
0x1002 jz 0x3
0x1004 call 0x1234
0x1007  

ดูว่าสั้นแค่ไหน?

บางแหล่ง c เพิ่มเติม

int foo=10;
if ( foo==0 ) wibble()

และแอสเซมบลี (ให้ถือว่าคอมไพเลอร์สมาร์ทเล็กน้อยที่สามารถแทนที่ == 0 โดยไม่มีการเปรียบเทียบ)

0x1000 ld a 0x10
0x1002 jz 0x3
0x1004 call 0x1234
0x1007  

ตอนนี้ให้ลองใช้การประชุมที่แท้จริง = 1

บางแหล่ง c เพิ่มเติม #define TRUE 1 int foo = TRUE; ถ้า (foo == TRUE) wibble ()

และการชุมนุม

0x1000 ld a 0x1
0x1002 cmp a 0x01
0x1004 jz 0x3
0x1006 call 0x1234
0x1009 

มาดูกันว่าเคสที่ไม่ใช่ศูนย์จริงสั้นเพียงใด

ซีพียูยุคแรก ๆ จริงๆมีชุดธงเล็ก ๆ ติดอยู่กับ Accumulator

ในการตรวจสอบว่า a> b หรือ a = b โดยทั่วไปใช้คำสั่งเปรียบเทียบ

  • ยกเว้น B เป็น ZERO ซึ่งในกรณีนี้แฟล็ก ZERO จะถูกตั้งค่า Implemented เป็น NOR แบบลอจิคัลที่เรียบง่ายหรือบิตทั้งหมดใน Accumulator
  • หรือเป็นลบซึ่งเพียงแค่ใช้ "sign bit" นั่นคือบิตที่สำคัญที่สุดของ Accumulator ถ้าคุณใช้เลขคณิตประกอบสองตัว (ส่วนใหญ่เราทำ)

ให้พูดย้ำเรื่องนี้ ใน CPU รุ่นเก่าบางรุ่นคุณไม่จำเป็นต้องใช้คำสั่งเปรียบเทียบสำหรับการสะสมเท่ากับ ZERO หรือการสะสมน้อยกว่าศูนย์

ทีนี้คุณจะเห็นว่าทำไมศูนย์ถึงอาจเป็นเท็จ?

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


2
ประเด็นของคุณไม่ได้อยู่ที่นี่เพราะสิ่งหนึ่งif (foo)และif (foo != 0)ควรสร้างรหัสเดียวกันและประการที่สองคุณแสดงให้เห็นว่าภาษาแอสเซมบลีที่คุณใช้จริง ๆ แล้วมีบูลีนโอเปอแรนต์และการทดสอบอย่างชัดเจน ยกตัวอย่างเช่นวิธีjz กล่าวอีกนัยหนึ่งjump if zero if (a == 0) goto target;และปริมาณไม่ได้ถูกทดสอบโดยตรง เงื่อนไขถูกแปลงเป็นแฟล็กบูลีนซึ่งถูกเก็บไว้ในคำของเครื่องพิเศษ จริง ๆ แล้วมันก็เป็นเหมือนcpu.flags.zero = (a == 0); if (cpu.flags.zero) goto target;
Kaz

ไม่มี Kaz, CPU รุ่นเก่าไม่ทำงานเช่นนั้น jz / jnz สามารถทำได้โดยไม่ต้องทำคำสั่งเปรียบเทียบ ซึ่งเป็นจุดที่ฉันโพสต์ทั้งหมดจริงๆ
ทิม Williscroft

2
ฉันไม่ได้เขียนอะไรเกี่ยวกับคำสั่งเปรียบเทียบ
Kaz

คุณสามารถอ้างถึงตัวประมวลผลที่มีjzคำสั่ง แต่ไม่jnz? (หรือชุดคำสั่งแบบมีเงื่อนไขอื่น ๆ )
Toby Speight

3

มีคำตอบมากมายที่แนะนำว่าการติดต่อระหว่าง 1 กับความจริงนั้นจำเป็นสำหรับคุณสมบัติทางคณิตศาสตร์บางอย่าง ฉันไม่สามารถหาทรัพย์สินดังกล่าวได้และแนะนำว่าเป็นการประชุมทางประวัติศาสตร์อย่างหมดจด

ด้วยเขตข้อมูลที่มีสององค์ประกอบเรามีสองการดำเนินการ: การเพิ่มและการคูณ เราสามารถแมปการดำเนินการบูลีนในฟิลด์นี้ได้สองวิธี:

ตามเนื้อผ้าเราระบุ True ด้วย 1 และ False ด้วย 0 เราระบุและกับ * และ XOR ด้วย + ดังนั้นหรือเติมอิ่มตัว

อย่างไรก็ตามเราสามารถระบุ True ได้อย่างง่ายดายด้วย 0 และ False ด้วย 1 จากนั้นเราจะระบุหรือด้วย * และ XNOR ด้วย + ดังนั้นและยังเพิ่มความอิ่มตัว


4
หากคุณได้ติดตามลิงก์ในวิกิพีเดียคุณอาจพบว่าแนวคิดของพีชคณิตแบบบูลถูกปิดเกี่ยวข้องกับฟิลด์ Galois ขององค์ประกอบสององค์ประกอบ ( en.wikipedia.org/wiki/GF%282%29 ) สัญลักษณ์ 0 และ 1 ใช้เพื่อแสดงถึงอัตลักษณ์การบวกและการคูณตามลำดับเนื่องจากตัวเลขจริงเป็นฟิลด์ที่มีการระบุตัวตนเป็นตัวเลข 0 และ 1
Giorgio

1
@ NeilG ฉันคิดว่าจอร์โจกำลังพยายามพูดว่ามันเป็นมากกว่าแค่การประชุม 0 และ 1 ในพีชคณิตแบบบูลนั้นโดยทั่วไปแล้วจะเหมือนกับ 0 และ 1 ใน GF (2) ซึ่งมีพฤติกรรมเกือบเท่ากับ 0 และ 1 ในจำนวนจริงโดยคำนึงถึงการบวกและการคูณ
svick

1
@svick: ไม่เพราะคุณสามารถเปลี่ยนชื่อการคูณและการเพิ่ม saturating เป็น OR และ AND จากนั้นพลิกฉลากเพื่อให้ 0 เป็น True และ 1 เป็นเท็จ จอร์โจบอกว่ามันเป็นแบบแผนของตรรกะบูลีนซึ่งถูกนำมาใช้เป็นแบบแผนของวิทยาศาสตร์คอมพิวเตอร์
Neil G

1
@Neil G: ไม่คุณไม่สามารถพลิก + และ * และ 0 และ 1 เนื่องจากฟิลด์ต้องการการกระจายตัวของการคูณมากกว่าการเพิ่ม (ดูen.wikipedia.org/wiki/Field_%28mathematics%29 ) แต่ถ้าคุณตั้ง +: = AND และ *: = XOR คุณจะได้รับ T XOR (T และ F) = T XOR F = T ในขณะที่ (T XOR T) และ (T XOR F) = F และ T = F ดังนั้นโดยการพลิกการดำเนินการและตัวตนของคุณ ไม่มีฟิลด์อีกต่อไป ดังนั้น IMO จึงกำหนด 0 และ 1 ในฐานะตัวตนของเขตข้อมูลที่เหมาะสมดูเหมือนว่าจะจับเท็จและเป็นความจริงโดยสุจริต
Giorgio

1
@giorgio: ฉันได้แก้ไขคำตอบเพื่อให้ชัดเจนว่าเกิดอะไรขึ้น
Neil G

3

น่าแปลกที่ศูนย์ไม่ผิดเสมอไป

โดยเฉพาะอย่างยิ่งการประชุม Unix และ Posix คือการกำหนดEXIT_SUCCESSเป็น 0 (และEXIT_FAILUREเป็น 1) จริงๆแล้วมันเป็นแบบแผนมาตรฐานของC !

ดังนั้นสำหรับ Posix shells และexit (2) syscalls, 0 หมายถึง "สำเร็จ" ซึ่งสังหรณ์ใจเป็นจริงมากกว่าเท็จ

โดยเฉพาะอย่างยิ่งเชลล์ifต้องการให้กระบวนการคืนค่าEXIT_SUCCESS(นั่นคือ 0) เพื่อติดตามสาขา "แล้ว"!

ใน Scheme (แต่ไม่ใช่ Common LISP หรือMELT ) 0 และ nil (เช่น()ใน Scheme) เป็นจริงเนื่องจากค่าเท็จเท่านั้นคือ#f

ฉันเห็นด้วยฉันกำลัง nitpicking!


3

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

คุณสามารถเขียนสิ่งต่าง ๆ เช่น:

if (modemctrl & MCTRL_CD) {
   /* carrier detect is on */
}

ค่อนข้างมากกว่า

if ((modemctrl & MCTRL_CD) != 0) {
    /* carrier detect is on */
}

ในตัวอย่างที่แยกตัวเดียวมันไม่ได้เลวร้ายนัก แต่การทำเช่นนั้นจะทำให้เสียความรู้สึก

การดำเนินการสนทนาเช่นเดียวกัน มันมีประโยชน์สำหรับผลลัพธ์ของการดำเนินการบูลีนเช่นการเปรียบเทียบเพียงแค่สร้าง 0 หรือ 1: สมมติว่าเราต้องการตั้งค่าบิตที่สามของคำบางคำขึ้นอยู่กับว่าmodemctrlผู้ให้บริการตรวจสอบบิต:

flags |= ((modemctrl & MCTRL_CD) != 0) << 2;

ที่นี่เราต้องมี!= 0, เพื่อลดผลลัพธ์ของการ&แสดงออกbiwise เป็น0หรือ1, แต่เนื่องจากผลลัพธ์เป็นจำนวนเต็ม, เราจึงไม่จำเป็นต้องเพิ่มนักแสดงที่น่ารำคาญเพื่อแปลงบูลีนเป็นจำนวนเต็มเพิ่มเติม

แม้ว่า C สมัยใหม่จะมีboolประเภท แต่ก็ยังคงความถูกต้องของรหัสเช่นนี้ทั้งคู่เพราะมันเป็นสิ่งที่ดีและเนื่องจากความแตกแยกครั้งใหญ่ที่มีความเข้ากันได้แบบย้อนหลังที่อาจเกิดขึ้นได้

exmaple อื่นที่ C คือเนียน: ทดสอบสองเงื่อนไขบูลีนเป็นสวิตช์สี่ทาง:

switch (foo << 1 | bar) {  /* foo and bar booleans are 0 or 1 */
case 0: /* !foo && !bar */
   break;
case 1: /* !foo && bar */
   break;
case 2: /* foo && !bar */
   break;
case 3: /* foo && bar */
   break;
}

คุณไม่สามารถแยกสิ่งนี้ออกจากโปรแกรมเมอร์ C โดยปราศจากการต่อสู้!

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


0

ค่าบูลีนหรือความจริงมีเพียง 2 ค่า จริงและเท็จ

สิ่งเหล่านี้ไม่ควรแสดงเป็นจำนวนเต็ม แต่เป็นบิต (0 และ 1)

การพูดจำนวนเต็มอื่น ๆ นอกเหนือจาก 0 หรือ 1 นั้นไม่ใช่เท็จเป็นข้อความที่ทำให้เกิดความสับสน ตารางความจริงจัดการกับค่าความจริงไม่ใช่จำนวนเต็ม

จากค่าความจริงที่คาดหวัง -1 หรือ 2 จะทำลายตารางความจริงทั้งหมดและตรรกะบูลีนใด ๆ ที่สอดคล้องกับพวกเขา

  • 0 และ -1 ==?!
  • 0 หรือ 2 ==?!

ภาษาส่วนใหญ่มักจะมีbooleanประเภทที่เมื่อส่งไปยังประเภทตัวเลขเช่นจำนวนเต็มเผยเท็จที่จะโยนเป็นค่าจำนวนเต็ม 0


1
0 AND -1 == ค่าบูลีนใด ๆ ก็ตามที่คุณส่งไป นั่นคือสิ่งที่คำถามของฉันเป็นเรื่องเกี่ยวกับทำไมหล่อให้พวกเขาหรือTRUE FALSEฉันไม่เคยพูด - บางทีฉันอาจจะทำ แต่มันไม่ได้ตั้งใจ - จำนวนเต็มเป็นจริงหรือเท็จฉันถามว่าทำไมพวกเขาถึงประเมินว่าจะใช้แบบไหน
Morwenn

-6

ในที่สุดคุณกำลังพูดถึงการทำลายภาษาหลักเพราะ API บางตัวเส็งเคร็ง Crappy API ไม่ใช่เรื่องใหม่และคุณไม่สามารถแก้ไขได้ด้วยการทำลายภาษา มันเป็นความจริงทางคณิตศาสตร์ที่ 0 เป็นเท็จและ 1 เป็นจริงและภาษาใด ๆ ที่ไม่เคารพสิ่งนี้จะแตกพื้นฐาน การเปรียบเทียบแบบสามทางเป็นโพรงและไม่มีธุรกิจที่มีผลการแปลงโดยปริยายboolเพราะให้ผลลัพธ์ที่เป็นไปได้สามประการ API แบบเก่าของ C นั้นมีการจัดการข้อผิดพลาดที่แย่มากและยังเป็นข้อผิดพลาดเนื่องจาก C ไม่มีคุณสมบัติด้านภาษาที่จำเป็นที่จะไม่มีส่วนต่อประสานที่น่ากลัว

โปรดทราบว่าฉันไม่ได้บอกว่าสำหรับภาษาที่ไม่มีการแปลงเป็นจำนวนเต็มโดยนัย> บูลีน


11
"มันเป็นความจริงทางคณิตศาสตร์ที่ 0 เป็นเท็จและ 1 เป็นจริง" Erm
R. Martinho Fernandes

11
คุณสามารถอ้างอิงการอ้างอิงสำหรับ "ข้อเท็จจริงทางคณิตศาสตร์ของคุณว่า 0 เป็นเท็จและ 1 เป็นจริง" ได้หรือไม่? คำตอบของคุณฟังดูเหมือนอันตราย
Dan Pichelman

14
มันไม่ใช่ข้อเท็จจริงทางคณิตศาสตร์ แต่เป็นแบบแผนทางคณิตศาสตร์มาตั้งแต่ศตวรรษที่ 19
Charles E. Grant

1
พีชคณิตแบบบูลจะถูกแสดงด้วยฟิลด์ จำกัด ที่ 0 และ 1 เป็นองค์ประกอบตัวตนสำหรับการดำเนินการที่มีลักษณะคล้ายกับการเพิ่มและการคูณ การดำเนินการเหล่านั้นตามลำดับ OR และ AND ในความเป็นจริงพีชคณิตแบบบูลเขียนเหมือนพีชคณิตทั่วไปซึ่งการตีข่าวจะหมายถึง AND และและ+สัญลักษณ์นั้นหมายถึง OR ดังนั้นสำหรับตัวอย่างเช่นวิธีabc + a'b'c (a and b and c) or (a and (not b) and (not c))
Kaz
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.