Proč je 0 false?

Tato otázka může znít hloupě, ale proč se 0 vyhodnotí jako false a jakákoli jiná [celočíselná] hodnota true je většina programovacích jazyků?

Porovnání řetězců

Protože se otázka zdá trochu příliš jednoduché, vysvětlím si to trochu víc: za prvé, každému programátorovi se to může zdát evidentní, ale proč by neexistoval programovací jazyk – ve skutečnosti může být, ale žádný, který jsem použil – kde 0 se vyhodnotí na true a všechny ostatní [celé číslo] hodnoty na false? Tato poznámka může vypadat náhodně, ale mám několik příkladů, kde to mohl být dobrý nápad. Nejprve si vezměme příklad řetězcového třícestného srovnání, vezmu C strcmp jako příklad: každý programátor, který zkouší C jako svůj první jazyk, může být v pokušení napsat následující kód:

Protože strcmp vrací 0 který se vyhodnotí jako false když jsou řetězce stejné, to, o co se pokusil začínající programátor, selhává bídně a obecně nejprve nechápe proč. Pokud byla 0 vyhodnocena jako true, mohla být tato funkce použita v nejjednodušším výrazu – výše uvedeném – při porovnávání rovnosti, a správné kontroly pro -1 a 1 by byly provedeny pouze v případě potřeby. Za návratový typ bychom považovali většinu času za bool (myslím to v našich myslích).

Navíc pojďme zavést nový typ, sign, který má pouze hodnoty -1, 0 a 1. To může být docela užitečné. Představte si, že v C ++ je operátor vesmírné lodi a my ho chceme pro std::string (dobře, již existuje funkce compare, ale provozovatel vesmírné lodi je zábavnější). Deklarace by v současné době byla následující:

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

Byl 0 vyhodnocen jako true provozovatel kosmické lodi by vůbec neexistoval a mohli bychom deklarovat operator== tímto způsobem:

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

Toto operator== by zpracovali třícestné srovnání najednou a stále je lze použít k provedení následující kontroly, přičemž v případě potřeby stále můžete zkontrolovat, který řetězec je lexikograficky lepší než ten druhý:

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

Zpracování starých chyb

Nyní máme výjimky, takže tato část platí pouze pro staré jazyky, kde nic takového neexistuje existují (například C). Podíváme-li se na standardní knihovnu C (a také na POSIX), můžeme si být jisti, že funkce maaaaany vrací 0, když je úspěšná, a celé číslo jinak. Bohužel jsem viděl některé lidi udělejte takové věci:

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

Pokud přemýšlíme o tom, jak si myslíme programování máme často následující vzor uvažování:

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

Pokud se zamyslíme nad opět by mělo smysl dát jedinou neutrální hodnotu 0 na yes (a takto C funkce fungují), zatímco všechny ostatní hodnoty mohou být k vyřešení mnoha případů no. Ve všech programovacích jazycích, které znám (kromě možná některých experimentálních esoterických jazyků), že yes se vyhodnotí jako false v if stavu Všechny no případy se vyhodnotí jako true. Existuje mnoho situací, kdy „to funguje“ představuje jeden případ, zatímco „to nefunguje“ představuje mnoho pravděpodobných příčin. Pokud o tom tak přemýšlíme, necháme 0 vyhodnotit na true a zbytek na false by dávalo mnohem větší smysl.

Závěr

Můj závěr je v zásadě mou původní otázkou: proč jsme navrhli jazyky, kde 0 je false a ostatní hodnoty jsou true s přihlédnutím k mým několika výše uvedeným příkladům a možná i dalším, na které jsem nemyslel?

Pokračování: Je hezké vidět, že existuje mnoho odpovědí s mnoha nápady a možnými důvody aby to tak bylo. Miluji, jak vášnivě to vypadá.Původně jsem tuto otázku položil z nudy, ale protože se zdáš tak vášnivý, rozhodl jsem se jít trochu dále a zeptat se na zdůvodnění Booleovy volby pro 0 a 1 on Math.SE 🙂

Komentáře

  • strcmp() není dobrým příkladem pro true nebo false, protože vrací 3 různé hodnoty. A budete překvapeni, když začnete používat prostředí, kde 0 znamená true a cokoli jiného znamená false.
  • @ ott–: Ve skořápkách Unixu 0 znamená úspěch a ne -zero znamená selhání – není to úplně to samé jako “ true “ a “ false „.
  • @KeithThompson: V Bash (a dalších skořápkách) “ úspěch “ a “ selhání “ jsou opravdu stejné jako “ true “ a “ false „. Vezměme si například výrok if true ; then ... ; fi, kde true je příkaz, který vrací nulu a říká if ke spuštění ....
  • V hardwaru neexistují žádné booleovské hodnoty, pouze binární čísla a ve většině historických ISA se uvažuje nenulové číslo jako “ true “ ve všech pokynech podmíněného větvení (pokud ‚ znovu nepoužívají příznaky namísto). Nízkoúrovňové jazyky jsou tedy ve všech ohledech povinny řídit se základními vlastnostmi hardwaru.
  • @MasonWheeler Mít booleovský typ neznamená ‚ nic. Například python typ bool, ale srovnání / pokud podmínky atd. Mohou mít jakoukoli návratovou hodnotu.

Odpověď

0 je false, protože jsou oba nulové prvky v běžných semirings . I když se jedná o odlišné datové typy, má intuitivní smysl převádět mezi nimi, protože patří do izomorfních algebraických struktur.

  • 0 je identita pro přidání a nula pro násobení. To platí pro celá čísla a racionální data, ale ne čísla s plovoucí desetinnou čárkou IEEE-754: 0.0 * NaN = NaN a 0.0 * Infinity = NaN .

  • false je identita pro Boolean xor (⊻) a nula pro Boolean a (∧). Pokud jsou booleovské reprezentovány jako {0, 1} – množina celých čísel modulo 2 – můžete si představit ⊻ jako doplněk bez přenosu a ∧ jako násobení.

  • "" a [] jsou identitou pro zřetězení, ale existuje několik operací, pro které mají smysl jako nula. Opakování je jedno, ale opakování a zřetězení se nedistribuují, takže tyto operace netvoří semirování.

Takové implicitní převody jsou užitečné v malých programech, ale ve velkých může programy ztížit. Pouze jeden z mnoha kompromisů v jazykovém designu.

Komentáře

  • Pěkné, že jste zmínili seznamy. (BTW, nil je prázdný seznam [] i false hodnota v Common Lisp ; existuje tendence slučovat identity z různých datových typů?) Stále musíte vysvětlovat, proč je přirozené považovat false za aditivní identitu a true za multiplikativní identitu, a nikoli naopak. Nelze ‚ považovat true za identifikaci pro AND a nulu pro OR?
  • +1 pro odkazování na podobné identity. Nakonec odpověď, která se ‚ neváže pouze na “ konvenci, vypořádejte se s ní „.
  • +1 za poskytnutí podrobných údajů o konkrétní a velmi staré matematice, ve které se toto dodržovalo a dlouho dávalo smysl
  • Tato odpověď není ‚ nedává smysl. true je také identita a nula polokoulí (booleovská a / nebo). Neexistuje žádný důvod, Appartova konvence, aby zvážila, že false je blíže 0 než true.
  • @TonioElGringo: Rozdíl mezi true a false je rozdíl mezi XOR a XNOR. Jeden může tvořit izomorfní kruhy pomocí AND / XOR, kde true je multiplikativní identita a false aditivní, nebo pomocí OR a XNOR, kde false je multiplikativní identita a true je aditivní, ale XNOR se obvykle nepovažuje za běžný základní operace taková, jaká je XOR.

Odpověď

Protože matematika funguje.

FALSE OR TRUE is TRUE, because 0 | 1 is 1. ... insert many other examples here. 

Programy C mají tradičně podmínky jako

 if (someFunctionReturningANumber())  

spíše než

 if (someFunctionReturningANumber() != 0)  

protože koncept nuly je ekvivalentní k false je dobře pochopen.

Komentáře

  • Jazyky jsou navrženy tak, protože matematika má smysl. To přišlo jako první.
  • @Morwenn, to sahá až do 19. století a George Boole. Lidé reprezentují False jako 0 a True jako! 0 déle, než tomu bylo u počítačů.
  • Nechápu ‚ proč matematika ‚ nefunguje jinak, pokud změníte pouze všechny definice tak, že AND je + a OR je *.
  • Přesně: matematika funguje oběma způsoby a odpověď na tato otázka se zdá být čistě konvenční.
  • @Robert Je ‚ skvělé, kdybyste mohli vysvětlit “ matematické podklady “ ve vašem příspěvku.

Odpověď

Jak již řekli ostatní, matematika byla na prvním místě. Z tohoto důvodu je 0 false a 1 je true.

O které matematice mluvíme? Booleovské algebry , které pocházejí z poloviny 19. století, dlouho předtím, než se objevily digitální počítače.

Dalo by se také říci, že konvence vycházela z výrokové logiky , která byla dokonce starší než booleovské algebry. Toto je formalizace mnoha logických výsledků, které programátoři znají a milují (false || x se rovná x, true && x se rovná x atd.).

V zásadě mluvíme o aritmetice na množině se dvěma prvky. Přemýšlejte o počítání v binárním formátu. Booleovské algebry jsou původem tohoto konceptu a jeho teoretickým základem. Konvence jazyků jako C jsou jen přímočará aplikace.

Komentáře

  • Mohli byste , určitě. Ale zachování “ standardního “ způsobu dobře zapadá do obecné aritmetiky (0 + 1 = 1, ne 0 + 1 = 0).
  • Ano, ale pravděpodobně byste psali AND s + a OR s *, pokud byste také obrátili definice.
  • Matematika ne ‚ Nejprve přijde. Matematika poznala, že 0 a 1 tvoří pole, ve kterém AND je jako násobení a OR jako sčítání.
  • @ Kaz: Ale {0, 1} s OR a AND netvoří pole.
  • Trochu mi vadí, že více odpovědí a komentářů říká, že true = 1. To ‚ není zcela přesné, protože true != 0 což není úplně stejné. Jeden důvod (ne jediný), proč by se člověk měl vyvarovat srovnávání jako if(something == true) { ... }.

Odpovědět

Myslel jsem, že to souvisí s „dědičností“ z elektroniky a také s booleovskou algebrou, kde

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

strcmp vrací 0, když jsou řetězce stejné, souvisí s jeho implementací, protože to, co ve skutečnosti dělá, je výpočet „vzdálenosti“ mezi těmito dvěma řetězci. To, že 0 je také považováno za nepravdivé, je jen náhoda.

vrácení 0 o úspěchu dává smysl protože 0 v tomto případě znamená žádná chyba a jakékoli jiné číslo by bylo kódem chyby. Použití jakéhokoli jiného čísla pro úspěch by nemělo smysl, protože máte pouze jeden úspěšný kód, zatímco můžete mít několik chybových kódů. Použili jste „Fungovalo to?“ jako výraz výrazu if a řekni 0 = ano by dával větší smysl, ale výraz je správnější „Pokazilo se něco?“ a pak uvidíte, že 0 = ne má velký smysl. Přemýšlení o false/true zde opravdu nedává smysl, protože ve skutečnosti no error code/error code.

Komentáře

  • Haha, jsi první, kdo výslovně uvede otázku chyby vrácení. Už jsem věděl, že jsem si to vyložil svým vlastním způsobem, a mohl jsem se zeptat na druhou stranu, ale vy ‚ jste první, kdo to výslovně vyjádří (z mnoha odpovědí a komentářů).Vlastně bych ‚ neřekl, že jeden nebo druhý způsob nedává smysl, ale víc, že oba dávají smysl různými způsoby 🙂
  • Vlastně I ‚ řekněme 0 pro success/no error je jediná věc, která má smysl, když jiná celá čísla představují chybové kódy . To, že 0 také představuje false v ostatních případech, na tom ‚ opravdu nezáleží, protože ‚ tady vůbec nemluvíme o true nebo false;)
  • měl jsem stejný nápad, takže jsem zvýšil
  • váš názor na strcmp() výpočet vzdálenosti je celkem dobrý. Pokud by to bylo nazýváno strdiff(), pak by if (!strdiff()) bylo velmi logické.
  • “ elektronika […] kde 0 = […] nepravda, 1 = […] pravda “ – i v elektronice je to jen onvence a není ‚ jediná. Říkáme tomu pozitivní logika, ale můžete také použít zápornou logiku, kde kladné napětí označuje nepravdivé a záporné označuje pravdivé. Potom se obvod, který ‚ d použijete pro AND, stane OR, OR se stane AND atd. Kvůli zákonu společnosti De Morgan ‚ to všechno skončí jako rovnocenné. Někdy ‚ pro větší pohodlí najdete část elektronického obvodu implementovanou v záporné logice, kdy jsou názvy signálů v této části zaznamenány s pruhem nad nimi.

Odpověď

Jak je vysvětleno v tomto článku , hodnoty false a true by neměly být zaměňovány s celými čísly 0 a 1, ale lze je identifikovat pomocí prvků pole Galois (konečné pole) dvou prvků (viz zde ).

Pole je sada se dvěma operacemi, které splňují určité axiomy.

Symboly 0 a 1 se běžně používají k označení aditivní a multiplikativní identity pole, protože skutečná čísla jsou také polem (nikoli však konečným), jehož identitou jsou čísla 0 a 1.

Aditivní identita je prvek 0 pole, takže pro všechna x:

x + 0 = 0 + x = x 

a multiplikativní identita je prvkem 1 pole, takže pro všechna x:

x * 1 = 1 * x = x 

Konečné pole dvou prvků má pouze tyto dva prvky, jmenovitě aditivní identita 0 (nebo false) a multiplikativní identita 1 (nebo true). Dvě operace tohoto pole jsou logický XOR (+) a logický AND (*).

Poznámka. Pokud otočíte operace (XOR je multiplikace a AND je sčítání), pak multiplikace není distribuční přes sčítání a již nemáte pole. V takovém případě nemáte důvod volat dva prvky 0 a 1 (v libovolném pořadí). Všimněte si také, že nemůžete zvolit operaci OR místo XOR: bez ohledu na to, jak interpretujete OR / AND jako sčítání / násobení, výsledná struktura není pole (ne všechny inverzní prvky existují, jak to vyžadují axiomy pole). >

Pokud jde o funkce C:

  • Mnoho funkcí vrací celé číslo, které je kódem chyby. 0 znamená ŽÁDNOU CHYBU.
  • Intuitivně funkce strcmp vypočítá rozdíl mezi dvěma řetězci. 0 znamená, že mezi dvěma řetězci není žádný rozdíl, tj. Že dva řetězce jsou stejné.

Výše uvedená intuitivní vysvětlení mohou pomoci zapamatovat si interpretaci návratových hodnot, ale je ještě snazší stačí zkontrolovat dokumentaci knihovny.

Komentáře

  • +1, které ukazují, že pokud je libovolně zaměníte, matematika již nebude fungovat.
  • Převráceno: Vzhledem k poli se dvěma prvky a operacemi * a + identifikujeme True s 0 a False s 1. Identifikujeme OR s * a XOR s +.
  • Zjistíte, že oba těchto identifikací se provádí ve stejném poli a obě jsou v souladu s pravidly logické logiky. Vaše poznámka je bohužel nesprávná 🙂
  • Pokud předpokládáte, že True = 0 a XOR je +, pak True musí být identita pro XOR. Ale není to proto, že True XOR True = False. Pokud předefinujete operaci XOR na True tak, aby True XOR True = True. Pak samozřejmě vaše konstrukce funguje, protože jste právě přejmenovali věci (v jakékoli matematické struktuře můžete vždy úspěšně vytvořit permutaci názvu a získat izomorfní strukturu). Na druhou stranu, pokud necháte True, False a XOR svůj obvyklý význam, pak True XOR True = False a True nemůže být aditivní identitou, tj. True nemůže být 0.
  • @Giorgio: Opravil jsem svoji konstrukci podle vašeho komentáře v mém posledním komentáři …

Odpověď

Měli byste vzít v úvahu, že alternativní systémy mohou být také přijatelnými rozhodnutími o návrhu.

Mušle: stav ukončení 0 je pravdivý, nenulový je nepravdivý

Příklad toho, jak mušle ošetřují 0 stav ukončení jako true již byl zmíněn.

 $ ( 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  

Důvodem je, že existuje jeden způsob, jak uspět, ale mnoho způsobů, jak selhat, takže použití 0 jako speciální hodnoty, což znamená „žádné chyby“, je pragmatické.

Ruby: 0 je jako každé jiné číslo

Mezi „běžnými“ programovacími jazyky jsou některé odlehlé hodnoty, například Ruby, které považují 0 za skutečnou hodnotu.

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

zdůvodnění spočívá v tom, že pouze false a nil by měly být nepravdivé. Pro mnoho Ruby nováčků je to „gotcha. V některých případech je však hezké, že s nulou se zachází stejně jako s jakýmkoli jiným číslem.

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" 

Nicméně , takový systém funguje pouze v jazyce, který je schopen odlišit booleovské hodnoty jako samostatný typ od čísel. V dřívějších dobách výpočtů programátoři pracující s montážním jazykem nebo surovým strojovým jazykem neměli takový luxus. Pravděpodobně je přirozené zacházet s 0 jako se stavem „prázdné“ a nastavit bit na 1 jako příznak, když kód zjistil, že se něco stalo. Rozšířením konvence vyvinula, že s nulou se zachází jako s falešnou, a s nenulovými hodnotami se zachází jako s pravdou. Nemusí to však tak být.

Java: S čísly nelze vůbec zacházet jako s booleovci

V Javě true a false jsou jediné booleovské hodnoty. Čísla nejsou booleovské hodnoty a nelze je ani vracet do booleanů ( Java Language Specification, Sec 4.2.2 ):

Mezi integrálními typy a typem boolean neexistují žádné přetypování. .

Toto pravidlo se otázce úplně vyhne – všechny booleovské výrazy musí být v kódu výslovně napsány.

Komentáře

  • Rebol a Red považují hodnoty INTEGER! s hodnotou 0 za pravdivé a mají samostatný ŽÁDNÝ! typ (pouze s jednou hodnotou, ŽÁDNÝ) považováno kromě LOGIC! false za podmíněné false. ‚ jsem zjistil významnou frustraci při pokusu o napsání kódu JavaScript, který považuje 0 za nepravdivou; je přírůstek zjevně neohrabané rozhodnutí pro dynamicky psaný jazyk. Pokud chcete otestovat něco, co může mít hodnotu null nebo 0, musíte nakonec napsat if (thing === 0), to prostě není super.
  • @HostileFork I don ‚ nevím. Zjistil jsem, že má smysl, že 0 je true (jako každé jiné celé číslo) v dynamickém jazyce. Někdy se mi stalo, že jsem chytil 0, když jsem se pokoušel chytit None v Pythonu, a to může být někdy docela těžké najít.
  • Ruby není odlehlá. Ruby to bere od Lisp (Ruby se dokonce tajně nazývá “ MatzLisp „). Lisp je běžný jazyk v počítačové vědě. Nula je také jen skutečnou hodnotou v prostředí POSIX, protože ‚ obsahuje text: if [ 0 ] ; then echo this executes ; fi. Hodnota falešných dat je prázdný řetězec a testovatelná lež je stav neúspěšného ukončení příkazu, který je reprezentován non -zero.

Odpověď

Než se budeme zabývat obecným případem, můžeme probrat vaše příklady počítadel.

Porovnání řetězců

Totéž platí pro mnoho druhů srovnání. Taková srovnání počítají vzdálenost mezi dvěma objekty. Když jsou objekty stejné, vzdálenost je minimální. Když tedy „srovnání proběhne úspěšně“, je hodnota 0. Ale návratová hodnota strcmp není není boolean, je to vzdálenost a že to, co chytí nevědomé programátory, kteří dělají if (strcmp(...)) do_when_equal() else do_when_not_equal().

V C ++ bychom mohli redesignovat strcmp a vrátit Distance objekt, který přepíše operator bool() vrátit true, když je 0 (ale pak by vás kousla jiná sada problémů). Nebo v prostém C stačí mít streq funkci, která vrací 1, když jsou řetězce stejné, a 0 jinak.

Volání API / kód ukončení programu

Zde vás zajímá důvod, proč se něco pokazilo, protože to způsobí, že rozhodnutí budou chybná. Když se věci podaří, nechcete nic konkrétního vědět – váš záměr je realizován. Návratová hodnota proto musí tuto informaci sdělit. není boolean, je to chybový kód. Speciální hodnota chyby 0 znamená „žádná chyba“. Zbytek rozsahu představují místně smysluplné chyby, se kterými se musíte vypořádat (včetně 1, což často znamená „nespecifikovanou chybu“).

Obecný případ

Zbývá nám tedy otázka: proč jsou logické hodnoty True a False běžně reprezentované 1, respektive 0?

Kromě subjektivního argumentu „cítím se to lépe“ je zde i několik důvodů (subjektivních):

  • analogie elektrického obvodu. Proud je ZAPNUTÝ na 1 s a VYPNUTÝ na 0 s. Mám rád společné (1, Yes, True, On) a (0, No, False, Off), spíše než další mix

  • inicializace paměti. Když memset(0) spoustu proměnných (ať už jsou to ints, floats, bools), chci, aby jejich hodnota odpovídala nejkonzervativnějším předpokladům. Např. můj součet je původně 0, predikát je False atd.

Možná všechny tyto důvody souvisejí s mým vzděláním – kdybych se naučil spojovat 0 s True z Na začátku bych šel opačně.

Komentáře

  • Ve skutečnosti existuje alespoň jeden programovací jazyk, který považuje 0 za pravdivou. Unixový shell.
  • +1 pro řešení skutečného problému: Většina otázek Morwenn ‚ není ‚ t o bool vůbec.
  • @ dan04 Je. Celý příspěvek pojednává o důvodech výběru obsazení od int do bool v mnoha programovacích jazycích. Srovnání a gesta chybových příkladů jsou jen příklady míst, kde by to mělo smysl dávat jiným způsobem, než by to mělo ‚ s aktuálně provedené.

Odpověď

Z pohledu vysoké úrovně hovoříte o třech zcela odlišných datových typech:

  1. Boolean. Matematická konvence v booleovské algebře je použití 0 pro false a 1 pro true, takže má smysl dodržovat tuto konvenci. Myslím, že tento způsob má také větší smysl intuitivně.

  2. Výsledek srovnání. tři hodnoty: <, = a > (všimněte si, že žádná z nich není true). Pro ně má smysl používat hodnoty -1, 0 a 1 (nebo obecněji záporná hodnota, nula a kladná hodnota).

    Pokud chcete zkontrolovat rovnost a Máte pouze funkci, která provádí obecné srovnání, myslím, že byste to měli udělat explicitně pomocí něčeho jako strcmp(str1, str2) == 0. Používání ! v této situaci považuji za matoucí, protože s logickou hodnotou zachází, jako by to byla logická hodnota.

    Mějte také na paměti toto srovnání a rovnost nemusí být totéž. Například pokud objednáváte lidi podle data narození, Compare(me, myTwin) by měl vrátit 0 , ale Equals(me, myTwin) by měl vrátit false.

  3. Úspěch nebo neúspěch funkce , případně také s podrobnostmi o tomto úspěchu nebo neúspěchu. Pokud mluvíte o Windows, pak se tento typ nazývá HRESULT a nenulová hodnota nemusí nutně znamenat selhání. negativní hodnota ve skutečnosti označuje selhání a nezáporný úspěch. Hodnota úspěchu je velmi často S_OK = 0, ale může to být například S_FALSE = 1 nebo jiné hodnoty.

Zmatek vychází ze skutečnosti že tři logicky zcela odlišné datové typy jsou ve skutečnosti reprezentovány jako jediný datový typ (celé číslo) v jazyce C a v některých dalších jazycích a že můžete použít celé číslo v podmínce. Ale nemyslím si, že by dávalo smysl předefinovat boolean, aby bylo používání některých neboolejských typů v podmínkách jednodušší.

Zvažte také jiný typ, který se často používá v podmínce v C: ukazatel . Je přirozené považovat NULL -pointer (který je reprezentován jako 0) jako false. Sledování vašeho návrhu by tedy také zkomplikovalo práci s ukazateli. (Osobně však dávám přednost výslovnému porovnání ukazatelů s NULL, místo toho, abych s nimi zacházeli jako s booleovci.)

Odpověď

Nula může být nepravdivá, protože většina CPU má příznak NULA, který lze použít k větvení. Uloží operaci porovnání.

Uvidíme proč.

Nějaký psuedocode, protože publikum pravděpodobně nečte sestavu

c-source simple loop calls wibble 10 times

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

nějaké předstírané shromáždění za to

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- zdroj další jednoduchý smyčkové volání 10krát křičet

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

v tomto případě předstírat nějaké sestavení

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 

další zdroj c

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

a sestava

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

zobrazit, jak je to krátké?

nějaký další zdroj c

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

a sestavení (předpokládejme okrajově chytrý kompilátor, který může nahradit == 0 bez srovnání )

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

Nyní můžeme vyzkoušet konvenci true = 1

další zdroj c #define TRUE 1 int foo = TRUE; if (foo == PRAVDA) wibble ()

a sestava

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

vidíte, jak krátký je případ s nenulovou pravdou?

Opravdu časné CPU měly k Akumulátoru připojeny malé sady příznaků.

Chcete-li zkontrolovat, zda a> b nebo a = b obecně trvá instrukci porovnání.

  • Pokud B není buď NULA – v takovém případě je nastaven příznak NULA Implementován jako jednoduchý logický NOR nebo všechny bity v Akumulátoru.
  • Nebo NEGATIVNÍ, ve kterém stačí použít „sign bit“, tj. nejvýznamnější bit Akumulátoru pokud používáte aritmetiku dvou doplňků. (Většinou ano)

Pojďme to přeformulovat. U některých starších procesorů jste nemuseli používat instrukci porovnání pro akumulátor rovný NULE nebo akumulátor menší než nula.

Nyní vidíte, proč by nula mohla být nepravdivá?

Vezměte prosím na vědomí, že se jedná o psuedo-kód a žádná skutečná sada instrukcí nevypadá úplně takto. Pokud znáte sestavení, víte, že zde hodně zjednodušuji. Pokud víte něco o designu kompilátoru, nemusíte tuto odpověď číst. Každý, kdo ví něco o rozvinutí smyčky nebo předpovědi větve, je pokročilá třída v hale 203.

Komentáře

  • Váš názor zde není příliš dobrý, protože jednak if (foo) a if (foo != 0) by měl vygenerovat stejný kód a za druhé ‚ znovu ukazujete, že jazyk sestavení, který ‚ používáte, má ve skutečnosti explicitní booleovské operandy a testuje je. Například jz znamená jump if zero. Jinými slovy if (a == 0) goto target; . A množství se ani přímo netestuje; podmínka se převede na logický příznak, který je uložen ve speciálním strojovém slově. ‚ je to vlastně spíše jako cpu.flags.zero = (a == 0); if (cpu.flags.zero) goto target;
  • Ne Kaz, starší CPU ‚ s takhle nefungovaly. T he jz / jnz lze provést bez provedení srovnávací instrukce. Což byl vlastně důvod celého mého příspěvku.
  • O instrukci pro srovnání jsem nic ‚ nenapsal.
  • Můžete mi citovat procesor, který má jz instrukci, ale žádný jnz? (nebo jakákoli jiná asymetrická sada podmíněných pokynů)

Odpověď

Existuje mnoho odpovědí, které naznačují, že korespondence mezi 1 a true je vyžadována nějakou matematickou vlastností. Nemohu najít žádnou takovou vlastnost a navrhnout, aby se jednalo o čistě historickou konvenci.

Vzhledem k poli se dvěma prvky máme dvě operace: sčítání a násobení. Booleovské operace v tomto poli můžeme mapovat dvěma způsoby. :

Tradičně identifikujeme True s 1 a False s 0. Identifikujeme AND s * a XOR s +. OR tedy nasycuje sčítání.

Mohli bychom však stejně snadno identifikovat True s 0 a False s 1. Pak identifikujeme OR s * a XNOR s +. AND tedy nasycuje sčítání.

Komentáře

  • Pokud sledovali jste odkaz na wikipedii, mohli jste zjistit, že koncept booleovské algebry je uzavřen v souvislosti s konceptem pole Galois dvou prvků ( en.wikipedia.org/wiki / GF% 282% 29 ). Symboly 0 a 1 se běžně používají k označení aditivní a multiplikativní identity, protože skutečná čísla jsou také polem, jehož identitou jsou čísla 0 a 1.
  • @NeilG Myslím, že Giorgio se to snaží říct ‚ s něčím víc než jen konvencí. 0 a 1 v booleovské algebře jsou v zásadě stejné jako 0 a 1 v GF (2), které se chovají téměř stejně jako 0 a 1 v reálných číslech, pokud jde o sčítání a násobení.
  • @svick: Ne , protože můžete jednoduše přejmenovat násobení a nasycení na OR nebo AND a poté převrátit popisky tak, že 0 je True a 1 je False.Giorgio říká, že šlo o konvenci logické logiky, která byla přijata jako konvence počítačové vědy.
  • @Neil G: Ne, nemůžete převrátit + a * a 0 a 1, protože pole vyžaduje distribuci násobení nad sčítáním (viz en.wikipedia.org/wiki/Field_%28mathematics%29 ), ale pokud nastavíte +: = AND a *: = XOR , dostanete T XOR (T AND F) = T XOR F = T, zatímco (T XOR T) AND (T XOR F) = F AND T = F. Proto převrácením operací a identit nemáte pole víc. Zdá se tedy, že IMO definující 0 a 1 jako identity příslušného pole zachycuje falešné a pravdivé docela věrně.
  • @giorgio: Upravil jsem odpověď, aby bylo zřejmé, o co jde.

Odpověď

Zvláštní je, že nula není vždy falešná.

Zejména konvence Unix a Posix je definovat EXIT_SUCCESS jako 0 (a EXIT_FAILURE jako 1). Ve skutečnosti je to dokonce standardní konvence C !

Takže pro skořápky Posix a výstup (2) syscalls, 0 znamená „úspěšný“, což je intuitivně více pravdivé než nepravdivé.

Zejména shell „s if chce proces vrací EXIT_SUCCESS (tj. 0) a sleduje jeho větev „then“!

Ve schématu (ale ne v Common Lisp nebo v MELT ) 0 a nil (tj. () ve schématu) jsou pravdivé, protože jediná falešná hodnota je #f

Souhlasím, dusím se!

Odpověď

C se používá pro programování na nízké úrovni v blízkosti hardwaru, což je oblast, ve které někdy potřebujete přepínat mezi bitovými a logickými operacemi, na stejných datech. Požadavek na převod číselného výrazu na boolean, jen aby se provedl test, by se zahltil kód.

Můžete psát například:

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

spíše než

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

V jednom izolovaném příkladu to není tak špatné, ale to, co musíte udělat, bude nepříjemné.

Stejně tak můžete provádět operace. Pro výsledek booleovské operace, jako je srovnání, je užitečné pouze vyprodukovat 0 nebo 1: Předpokládejme, že chceme nastavit třetí bit nějakého slova podle toho, zda modemctrl má nosič detekovat bit:

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

Zde musíme mít != 0, aby se snížil výsledek biwise & výrazu na 0 nebo 1, ale protože výsledkem je pouze celé číslo, jsme ušetřeni nutnosti přidávat nějaké otravné obsazení pro další převod booleovského na celé číslo.

Přestože moderní C nyní má bool typu, stále zachovává platnost takového kódu, jednak proto, že je to dobrá věc, jednak kvůli masivnímu rozbití se zpětnou kompatibilitou, které by bylo jinak způsobeno.

Další příklad, kde je C úhledný: testování dvou booleovských podmínek jako čtyřcestného přepínače:

Toto byste programátorovi C bez boje nemohli vzít!

Nakonec C někdy slouží jako druh montážního jazyka na vysoké úrovni. V montážních jazycích také nemáme booleovské typy. Logická hodnota je jen bitová nebo nulová versus nenulová hodnota v paměťovém umístění nebo registru. Celočíselná nula, booleovská nula a nula adresy jsou všechny testovány stejným způsobem v instrukčních sadách montážního jazyka (a možná i s plovoucí desetinnou čárkou). Podobnost mezi jazykem C a jazykem sestavení je užitečná, například když se C používá jako cílový jazyk pro kompilaci jiného jazyka (dokonce i toho, který má silně napsané booleans!)

Odpovědět

Booleovská nebo pravdivá hodnota má pouze 2 hodnoty. Pravda a nepravda.

Ty by neměly být reprezentovány jako celá čísla, ale jako bity (0 a 1 ).

Říci, že jakékoli jiné celé číslo kromě 0 nebo 1 není nepravdivé, je matoucí. Tabulky pravdy se zabývají hodnotami pravdy, nikoli celými čísly.

Z prospektu hodnoty pravdy by -1 nebo 2 rozbily všechny tabulky pravd a jakoukoli logickou logiku s nimi spojenou.

  • 0 A -1 ==?!
  • 0 NEBO 2 ==?!

Většina jazyků má obvykle boolean typ, který při přetypování na typ čísla, jako je celé číslo, odhalí, že false bude přetypováno na celočíselnou hodnotu 0.

Komentáře

  • 0 AND -1 == na jakoukoli booleovskou hodnotu je vrhnete. To je ‚ moje otázka, proč je vrhat na TRUE nebo FALSE.Nikdy jsem neřekl – možná jsem to udělal, ale nebylo to zamýšleno – celá čísla byla pravdivá nebo nepravdivá, zeptal jsem se, proč se při booleovském hodnocení hodnotí podle toho.

Odpověď

Nakonec mluvíte o prolomení základního jazyka, protože některá API jsou mizerná. Crappy APIs are not new, and you can „t fix them by breaking the language. Je to matematický fakt, že 0 je false a 1 je true, a jakýkoli jazyk, který to nerespektuje, je zásadně porušen. Trojcestné srovnání je výklenek a nemá žádné podnikání s tím, že jeho výsledek implicitně převede na bool, protože vrátí tři možné výsledky. Stará rozhraní API C prostě mají strašnou manipulaci s chybami a jsou také omezena, protože C nemá potřebné jazykové funkce, aby neměla strašná rozhraní.

Všimněte si, že to neříkám pro jazyky, které nemají implicitní integer-> boolean conversion.

Komentáře

  • “ Je matematický fakt, že 0 je nepravdivé a 1 je pravda “ Hm.
  • Můžete uvést odkaz na svůj “ matematický fakt, že 0 je nepravdivé a 1 je true „? Vaše odpověď zní nebezpečně jako chvástat se.
  • ‚ to není matematický fakt, ale ‚ to bylo matematická konvence od 19. století.
  • Booleova algebra je reprezentována konečným polem, ve kterém jsou 0 a 1 prvky identity pro operace, které se podobají přidání a násobení. Těmito operacemi jsou OR a AND. Ve skutečnosti je booleovská algebra psána podobně jako normální algebra, kde juxtaposition označuje AND a symbol + označuje OR. Například abc + a'b'c znamená (a and b and c) or (a and (not b) and (not c)).

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *