Hvorfor er 0 falsk?

Dette spørgsmål lyder måske dumt, men hvorfor vurderes 0 til false og enhver anden [heltal] værdi til true er det meste af programmeringssprog?

Sammenligning af strenge

Da spørgsmålet synes at være et lidt for simpelt, vil jeg forklare mig lidt mere: først og fremmest kan det virke tydeligt for enhver programmør, men hvorfor ville der ikke være et programmeringssprog – der kan faktisk være, men ikke noget, jeg brugte – hvor 0 evalueres til true og alle de andre [heltal] værdier til false? Den ene bemærkning kan virke tilfældig, men jeg har et par eksempler, hvor det kan have været en god idé. Lad os først tage eksemplet med strenges trevejs sammenligning, jeg tager C “s strcmp som eksempel: enhver programmør, der prøver C som sit første sprog, kan blive fristet til at skrive følgende kode:

Da strcmp returnerer 0 som evalueres til false når strengene er ens, mislykkes det begyndende programmør forsøgte at gøre, og han forstår generelt ikke hvorfor i starten. Havde 0 evalueret til true i stedet, kunne denne funktion have været brugt i sit mest enkle udtryk – det ovenstående – når man sammenligner for ligestilling, og de korrekte kontroller for -1 og 1 ville kun være udført, når det var nødvendigt. Vi ville have betragtet returtypen som bool (efter vores mening mener jeg) det meste af tiden.

Lad os desuden introducere en ny type, sign, der bare tager værdier -1, 0 og 1. Det kan være ret praktisk. Forestil dig, at der er en rumskibsoperatør i C ++, og vi vil have den til std::string (godt, der er allerede compare -funktionen, men rumskibsoperatør er sjovere). Erklæringen vil i øjeblikket være den følgende:

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

Var 0 blevet vurderet til true, rumskibsoperatøren ville ikke engang eksistere, og vi kunne have erklæret operator== på den måde:

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

Denne operator== ville har håndteret trevejs sammenligning på én gang og kunne stadig bruges til at udføre følgende kontrol, mens de stadig er i stand til at kontrollere, hvilken streng der er leksikografisk bedre end den anden, når det er nødvendigt:

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

Gamle fejlhåndtering

Vi har nu undtagelser, så denne del gælder kun for de gamle sprog, hvor der ikke er sådan noget findes (f.eks. C). Hvis vi ser på Cs standardbibliotek (og POSIX-et også), kan vi med sikkerhed se, at maaaaany-funktioner returnerer 0, når det lykkes og ellers et helt tal. Jeg har desværre set nogle mennesker gør denne slags ting:

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

Hvis vi tænker på, hvordan vi tænker i programmering har vi ofte følgende ræsonnementsmønster:

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

Hvis vi tænker på det igen, det ville have været fornuftigt at sætte den eneste neutrale værdi, 0, til yes (og det er sådan, hvordan C “s funktioner fungerer), mens alle de andre værdier kan være der for at løse de mange tilfælde af no. Men i alle programmeringssprog, jeg kender (undtagen måske nogle eksperimentelle esotere sprog), at yes evalueres til false i en if -tilstand, wh ile alle no sager vurderes til true. Der er mange situationer, hvor “det virker” repræsenterer en sag, mens “det virker ikke” repræsenterer mange sandsynlige årsager. Hvis vi tænker over det på den måde, at have 0 evaluere til true og resten til false ville have gjort meget mere mening.

Konklusion

Min konklusion er i det væsentlige mit originale spørgsmål: hvorfor designede vi sprog, hvor 0 er false og de andre værdier er true under hensyntagen til mine få eksempler ovenfor og måske nogle flere, jeg ikke tænkte på?

Opfølgning: Det er dejligt at se, at der er mange svar med mange ideer og så mange mulige grunde for at det skal være sådan. Jeg elsker, hvor lidenskabelig du ser ud til at være ved det.Jeg stillede oprindeligt dette spørgsmål ud af kedsomhed, men da du synes så lidenskabelig, besluttede jeg at gå lidt længere og spørge om begrundelsen bag det boolske valg for 0 og 1 på Math.SE 🙂

Kommentarer

  • strcmp() er ikke noget godt eksempel på sand eller falsk, da den returnerer 3 forskellige værdier. Og du vil blive overrasket, når du begynder at bruge en skal, hvor 0 betyder sand, og alt andet betyder falsk.
  • @ ott–: I Unix-skaller betyder 0 succes og ikke -nul betyder fiasko – ikke helt det samme som ” true ” og ” false “.
  • @KeithThompson: I Bash (og andre skaller), ” succes ” og ” fiasko ” er virkelig det samme som ” sand ” og ” falsk “. Overvej for eksempel udsagnet if true ; then ... ; fi, hvor true er en kommando, der returnerer nul, og dette fortæller if for at køre ....
  • Der er ingen booleanske i hardware overhovedet, kun binære tal, og i de fleste historiske ISAer betragtes et ikke-nul tal som ” sand ” i alle de betingede forgreningsinstruktioner (medmindre de ‘ bruger flag i stedet). Så sprog på lavt niveau er under alle omstændigheder forpligtet til at følge de underliggende hardwareegenskaber.
  • @MasonWheeler At have en boolsk type betyder ikke ‘ t noget. For eksempel har python en bool -type, men sammenligninger / hvis forhold osv. Kan have en hvilken som helst returværdi.

Svar

0 er false fordi de begge er nul elementer til fælles semirings . Selvom de er forskellige datatyper, giver det intuitiv mening at konvertere mellem dem, fordi de tilhører isomorfe algebraiske strukturer.

  • 0 er identiteten til addition og nul til multiplikation. Dette gælder for heltal og rationelle, men ikke IEEE-754 flydende numre: 0.0 * NaN = NaN og 0.0 * Infinity = NaN .

  • false er identiteten for boolsk xor (⊻) og nul for boolsk og (∧). Hvis boolæere er repræsenteret som {0, 1} – heltal modulo 2 – kan du tænke på ⊻ som tilføjelse uden carry og ∧ som multiplikation.

  • "" og [] er identitet til sammenkædning, men der er flere operationer, som de giver mening som nul. Gentagelse er en, men gentagelse og sammenkædning distribuerer ikke, så disse operationer danner ikke en semiring.

Sådanne implicitte konverteringer er nyttige i små programmer, men i de store kan gøre programmer sværere at tænke over. Bare en af de mange kompromiser inden for sprogdesign.

Kommentarer

  • Dejligt, at du nævnte lister. (BTW, nil er både den tomme liste [] og værdien false i Common Lisp ; er der en tendens til at flette identiteter fra forskellige datatyper?) Du skal stadig forklare, hvorfor det er naturligt at betragte falsk som en additiv identitet og sand som en multiplikativ identitet og ikke omvendt. Er det ikke ‘ t muligt at overveje true som identifikationen for AND og nul for OR?
  • +1 for henvisning til lignende identiteter. Endelig et svar, der ikke ‘ t bare koger ned til ” konvention, behandler det “.
  • +1 for at give detaljer om en konkret og meget gammel matematik, hvor dette er blevet fulgt og længe givet mening
  • Dette svar ‘ t giver mening. true er også identiteten og nul for semirings (boolsk og / eller). Der er ingen grund, appart-konvention, til at overveje, at false er tættere på 0 end true.
  • @TonioElGringo: Forskellen mellem sand og falsk er forskellen mellem XOR og XNOR. Man kan danne isomorfe ringe ved hjælp af AND / XOR, hvor sand er multiplikativ identitet og falsk additiv, eller med OR og XNOR, hvor falsk er multiplikativ identitet og sand er additiv, men XNOR betragtes normalt ikke som en almindelig grundlæggende operation, som XOR er.

Svar

Fordi matematikken fungerer.

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

C-programmer har traditionelt betingelser som

 if (someFunctionReturningANumber())  

i stedet for

 if (someFunctionReturningANumber() != 0)  

fordi begrebet nul svarer til falsk er godt forstået.

Kommentarer

  • Sprogene er designet sådan, fordi matematikken giver mening. Det kom først.
  • @Morwenn, det går tilbage til det 19. århundrede og George Boole. Folk har repræsenteret False som 0 og True as! 0 i længere tid, end der har været computere.
  • Jeg kan ikke ‘ ikke se, hvorfor matematikken ikke ‘ t arbejde den anden vej, hvis du blot ændrer alle definitionerne, så AND er + og OR er *.
  • Præcis: matematikken fungerer begge veje, og svaret på dette spørgsmål ser ud til at være, at det er rent konventionelt.
  • @Robert Det ‘ Det ville være fantastisk, hvis du kunne stave ” matematiske understøtninger ” i dit indlæg.

Svar

Som andre har sagt, kom matematikken først. Dette er grunden til 0 er false og 1 er true.

Hvilken matematik taler vi om? Boolske algebraer , der stammer fra midten af 1800erne, længe før digitale computere kom sammen.

Du kan også sige, at konventionen kom ud af propositionelogik , som endda er ældre end boolske algebraer. Dette er formaliseringen af mange af de logiske resultater, som programmører kender og elsker (false || x er lig med x, true && x er lig med x og så videre).

Grundlæggende taler vi om aritmetik på et sæt med to elementer. Tænk på at tælle binært. Boolske algebraer er oprindelsen til dette koncept og dets teoretiske understøttelse. Konventionerne for sprog som C er bare en nem anvendelse.

Kommentarer

  • Du kunne helt sikkert. Men at holde det ” standard ” passer godt sammen med generel aritmetik (0 + 1 = 1, ikke 0 + 1 = 0).
  • Ja, men du ville formodentlig skrive AND med + og OR med * hvis du også vendte definitionerne.
  • Matematikken skete ‘ kommer ikke først. Matematik anerkendte, at 0 og 1 danner et felt, hvor AND er som multiplikation og OR er som tilføjelse.
  • @ Kaz: Men {0, 1} med OR og AND danner ikke et felt.
  • Det generer mig lidt, at flere svar og kommentarer siger, at true = 1. At ‘ ikke er helt nøjagtig, fordi true != 0 hvilket ikke er nøjagtigt det samme. Én grund (ikke den eneste) til, hvorfor man skal undgå sammenligninger som if(something == true) { ... }.

Svar

Jeg troede, det havde at gøre med “arv” fra elektronik og også boolsk algebra, hvor

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

strcmp returnerer 0, når strengene er ens, har at gøre med dens implementering, da det, den faktisk gør, er at beregne “afstanden” mellem de to strenge. At 0 tilfældigvis også betragtes som falsk, er bare en tilfældighed.

at returnere 0 til succes giver mening fordi 0 i dette tilfælde bruges til at betyde ingen fejl og ethvert andet nummer ville være en fejlkode. Brug af ethvert andet nummer til succes ville give mindre mening, da du kun har en enkelt succeskode, mens du kan have flere fejlkoder. Du bruger “Fungerede det?” som if-sætningsudtrykket og sige 0 = ja ville give mere mening, men udtrykket er mere korrekt “Gik der noget galt?” og så ser du, at 0 = nej giver meget mening. At tænke på false/true giver ikke mening her, da det faktisk er no error code/error code.

Kommentarer

  • Haha, du er den første til at udtrykke returfejlspørgsmålet eksplicit. Jeg vidste allerede, at jeg fortolkede det på min egen måde, og det kunne ved at spørge den anden vej, men du ‘ er den første, der udtrykkeligt udtrykker det (ud af de mange svar og kommentarer).Faktisk ville jeg ikke ‘ ikke sige, at den ene eller den anden måde ikke giver mening, men mere at begge giver mening på forskellige måder 🙂
  • Faktisk har jeg ‘ d siger 0 for success/no error er det eneste, der giver mening, når andre heltal repræsenterer fejlkoder . At 0 tilfældigvis også repræsenterer false i andre tilfælde betyder ikke ‘ ikke noget, da vi taler ikke ‘ overhovedet ikke om sandt eller falsk her;)
  • Jeg havde den samme idé, så jeg forøgede
  • Dit punkt om strcmp() at beregne afstanden er ret god. Hvis det var blevet kaldt strdiff(), ville if (!strdiff()) være meget logisk.
  • ” elektronik […] hvor 0 = […] falsk, 1 = […] sand ” – selv i elektronik er dette kun en konvention , og er ikke ‘ t den eneste. Vi kalder dette positiv logik, men du kan også bruge negativ logik, hvor en positiv spænding angiver falsk og negativ angiver sand. Derefter bliver det kredsløb, du ‘ bruger til AND, ELLER ELLER ELLER bliver OG osv. På grund af De Morgan ‘ s lov, ender det hele med at være ækvivalent. Nogle gange finder du ‘ en del af et elektronisk kredsløb implementeret i negativ logik for nemheds skyld, på hvilket tidspunkt navnene på signalerne i den del er noteret med en bjælke over dem.

Svar

Som forklaret i denne artikel , skal værdierne false og true ikke forveksles med heltalene 0 og 1, men kan identificeres med elementerne i Galois-feltet (endeligt felt) af to elementer (se her ).

Et felt er et sæt med to operationer, der opfylder visse aksiomer.

Symbolerne 0 og 1 bruges traditionelt til at betegne additiv og multiplikativ identitet i et felt, fordi de reelle tal også er et felt (men ikke et endeligt), hvis identitet er tallene 0 og 1.

Additividentiteten er elementet 0 i feltet, således at for alle x:

x + 0 = 0 + x = x 

og den multiplikative identitet er elementet 1 i feltet, således at for alle x:

x * 1 = 1 * x = x 

Det endelige felt af to elementer har kun disse to elementer, nemlig additiv identitet 0 (eller false) og den multiplikative identitet 1 (eller true). De to operationer i dette felt er den logiske XOR (+) og den logiske AND (*).

Bemærk. Hvis du vender operationerne (XOR er multiplikationen og AND er tilføjelsen), er multiplikationen ikke distribuerende over tilføjelse, og du har ikke et felt mere. I et sådant tilfælde har du ingen grund til at kalde de to elementer 0 og 1 (i en hvilken som helst rækkefølge). Bemærk også, at du ikke kan vælge operationen ELLER i stedet for XOR: uanset hvordan du fortolker OR / AND som addition / multiplikation, er den resulterende struktur ikke et felt (ikke alle inverse elementer eksisterer som krævet af feltaksiomerne).

Med hensyn til C-funktionerne:

  • Mange funktioner returnerer et heltal, der er en fejlkode. 0 betyder INGEN FEJL.
  • Intuitivt beregner funktionen strcmp forskellen mellem to strenge. 0 betyder, at der ikke er nogen forskel mellem to strenge, dvs. at to strenge er ens.

Ovenstående intuitive forklaringer kan hjælpe med at huske fortolkningen af returværdierne, men det er endnu lettere at tjek bare biblioteksdokumentationen.

Kommentarer

  • +1 for at vise, at hvis du vilkårligt bytter disse, fungerer matematikken ikke længere.
  • Vendt: Givet et felt med to elementer og operationer * og +, identificerer vi Sand med 0 og Falsk med 1. Vi identificerer ELLER med * og XOR med +.
  • Du finder ud af, at begge af disse identifikationer udføres over det samme felt, og begge er i overensstemmelse med reglerne i den boolske logik. Din note er desværre forkert 🙂
  • Hvis du antager, at True = 0, og XOR er +, skal True være identiteten for XOR. Men det er ikke fordi True XOR True = False. Medmindre du omdefinerer operationen XOR på True, så True XOR True = True. Så fungerer naturligvis din konstruktion, fordi du lige har omdøbt ting (i enhver matematisk struktur kan du altid med succes lave et navn permutation og få en isomorf struktur). På den anden side, hvis du lader sand, falsk og XOR have deres sædvanlige betydning, så kan sand XOR sand = falsk og sand ikke være additividentiteten, dvs. sand kan ikke være 0.
  • @Giorgio: Jeg korrigerede min konstruktion i henhold til din kommentar i min sidste kommentar…

Svar

Du skal overveje, at alternative systemer også kan være acceptable designbeslutninger.

Skaller: 0 exit-status er sand, ikke-nul er falsk

Eksemplet på skaller, der behandler en 0 exit-status som sand er allerede nævnt.

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

Begrundelsen der er, at der er én måde at lykkes på, men mange måder at mislykkes på, så det er pragmatisk at bruge 0 som den specielle værdi, der betyder “ingen fejl”.

Ruby: 0 er ligesom ethvert andet tal

Blandt “normale” programmeringssprog er der nogle outliers, såsom Ruby, der behandler 0 som en ægte værdi.

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

begrundelse er, at kun false og nil skal være falske. For mange Ruby-nybegyndere er det “sa gotcha. I nogle tilfælde er det dejligt, at 0 behandles ligesom ethvert andet nummer.

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" 

Dog , et sådant system fungerer kun på et sprog, der er i stand til at skelne booleanere som en separat type fra tal. I de tidligere computerdage havde programmører, der arbejdede med forsamlingssprog eller rå maskinsprog, ikke sådan luksus. Det er sandsynligvis bare naturligt at behandle 0 som “blank” tilstand og indstille lidt til 1 som et flag, når koden opdagede, at der skete noget. I forlængelse heraf udviklede konventionen sig, at nul blev behandlet som falsk, og at værdier, der ikke var nul, blev behandlet som sande. Det behøver dog ikke at være sådan.

Java: Tal kan slet ikke behandles som booleans

I Java true og false er de eneste booleske værdier. Tal er ikke booleanske og kan ikke engang kastes i booleanske ( Java Language Specification, Sec 4.2.2 ):

Der er ingen rollebesætninger mellem integraltyper og typen boolean .

Denne regel undgår bare spørgsmålet helt – alle boolske udtryk skal skrives eksplicit i koden.

Kommentarer

  • Rebol og Red behandler begge 0-værdiansatte INTEGER! -værdier som sande og har en separat NONE! -type (med kun en værdi, INGEN) behandlet som betinget falsk ud over LOGIC! false. Jeg ‘ har fundet betydelig frustration i at prøve at skrive JavaScript-kode, der behandler 0 som falsk; det er en inkr spiselig klodset beslutning for et dynamisk skrevet sprog. Hvis du vil teste noget, der kan være nul eller 0, skal du ende med at skulle skrive if (thing === 0), det er bare ikke sejt.
  • @HostileFork Jeg don ‘ ved ikke. Jeg finder ud af, at det giver mening, at 0 er true (som alle andre heltal) på et dynamisk sprog. Nogle gange tilfældigvis fangede jeg en 0, når jeg forsøgte at fange None i Python, og det kan nogle gange være ret svært at få øje på.
  • Ruby er ikke en outlier. Ruby tager dette fra Lisp (Ruby kaldes endda i hemmelighed ” MatzLisp “). Lisp er et almindeligt sprog inden for datalogi. Nul er også bare en ægte værdi i POSIX-skallen, fordi den ‘ er et stykke tekst: if [ 0 ] ; then echo this executes ; fi. Den falske dataværdi er en tom streng, og en testbar falskhed er en mislykket afslutningsstatus for en kommando, der er repræsenteret af en non -nul.

Svar

Før vi behandler den generelle sag, kan vi diskutere dine modeksempler.

Sammenligning af strenge

Det samme gælder faktisk for mange slags sammenligninger. Sådanne sammenligninger beregner en afstand mellem to objekter. Når objekterne er ens, er afstanden minimal. Så når “sammenligningen lykkes”, er værdien 0. Men virkelig er returværdien af strcmp ikke en boolsk, det er en afstand, og at hvad der fælder uvidende programmører, der gør if (strcmp(...)) do_when_equal() else do_when_not_equal().

I C ++ kunne vi redesigne strcmp for at returnere en Distance objekt, der tilsidesætter operator bool() for at returnere sandt når 0 (men du vil derefter blive bidt af et andet sæt problemer). Eller i almindelig C skal du bare have en streq -funktion, der returnerer 1, når strengene er ens, og ellers 0.

API-opkald / programudgangskode

Her er du ligeglad med årsagen til, at der gik noget galt, fordi dette vil føre beslutningerne op ved fejl. Når tingene lykkes, vil du ikke vide noget særligt – din hensigt realiseres. Returneringsværdien skal derfor formidle denne information.Det er ikke en boolsk, det er en fejlkode. Den specielle fejlværdi 0 betyder “ingen fejl”. Resten af området repræsenterer lokalt meningsfulde fejl, du skal håndtere (inklusive 1, hvilket ofte betyder “uspecificeret fejl”).

Generel sag

Dette efterlader os med spørgsmålet: hvorfor er boolske værdier True og False almindeligvis repræsenteret med henholdsvis 1 og 0?

Nå, udover det subjektive “det føles bedre på denne måde” argument, her er et par grunde (subjektivt også) jeg kan tænke på:

  • analog kredsløb. Strømmen er TÆNDT for 1s og OFF for 0s. Jeg kan godt lide at have (1, Ja, Sand, Til) sammen og (0, Nej, Falsk, Fra) i stedet for en anden blanding

  • initialisering af hukommelse. Når jeg memset(0) en masse variabler (det være sig ints, floats, bools), vil jeg have, at deres værdi svarer til de mest konservative antagelser. For eksempel. min sum er oprindeligt 0, predikatet er falsk osv.

Måske er alle disse grunde knyttet til min uddannelse – hvis jeg havde lært at forbinde 0 med True fra begynder, ville jeg gå omvendt.

Kommentarer

  • Faktisk er der mindst et programmeringssprog, der behandler 0 som sandt. Unix-skallen.
  • +1 til løsning af det virkelige problem: De fleste af Morwenn ‘ s spørgsmål er ikke ‘ t om bool overhovedet.
  • @ dan04 Det er det. Hele indlægget handler om begrundelsen for valget af rollebesætningen fra int til bool på mange programmeringssprog. Sammenligning og fejl gestion ting er bare eksempler på steder, hvor det at give en anden måde end det, det ‘ er i øjeblikket gjort, ville have mening.

Svar

Fra et højt perspektiv taler du om tre ganske forskellige datatyper:

  1. En boolsk. Den matematiske konvention i Boolsk algebra er at bruge 0 til false og 1 til true, så det giver mening at følge den konvention. Jeg tror, at denne måde også giver mere mening intuitivt.

  2. Resultatet af sammenligningen. Dette har tre værdier: <, = og > (bemærk at ingen af dem er true). For dem giver det mening at bruge værdierne henholdsvis -1, 0 og 1 (eller mere generelt en negativ værdi, nul og en positiv værdi).

    Hvis du vil kontrollere ligestilling a og du har kun en funktion, der udfører en generel sammenligning, jeg synes, du skal gøre det eksplicit ved at bruge noget som strcmp(str1, str2) == 0. Jeg finder det at bruge ! i denne situation forvirrende, fordi det behandler en ikke-boolsk værdi som om det var en boolsk.

    Husk også, at sammenligning og ligestilling behøver ikke at være den samme ting. Hvis du f.eks. bestiller folk efter deres fødselsdato, skal Compare(me, myTwin) returnere 0 , men Equals(me, myTwin) skal returnere false.

  3. En funktions succes eller fiasko muligvis også med detaljer om den succes eller fiasko. Hvis du “taler om Windows, kaldes denne type HRESULT og en værdi, der ikke er nul, betyder ikke nødvendigvis fiasko. Faktisk angiver en negativ værdi fiasko og ikke-negativ succes. Succesværdien er meget ofte S_OK = 0, men det kan f.eks. være S_FALSE = 1 eller andre værdier.

Forvirringen kommer fra det faktum det tre logisk ganske forskellige datatyper er faktisk repræsenteret som en enkelt datatype (et heltal) i C og nogle andre sprog, og at du kan bruge heltal i en tilstand. Men jeg tror ikke, det ville være fornuftigt at omdefinere boolsk for at gøre det ved at bruge nogle ikke-boolske typer i forhold enklere. . Der er det naturligt at behandle en NULL -pointer (som er repræsenteret som 0) som false Så at følge dit forslag ville det også gøre det vanskeligere at arbejde med pegepinde. (Selvom jeg personligt foretrækker eksplicit at sammenligne pegepunkter med NULL i stedet for at behandle dem som booleanske.)

Svar

Nul kan være falsk, fordi de fleste CPUer har et ZERO-flag, der kan bruges til at forgrene sig. Det gemmer en sammenligningshandling.

Lad os se hvorfor.

Nogle psuedocode, da publikum sandsynligvis ikke læser forsamling

c- kilde simple loop kalder wibble 10 gange

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

nogle foregiver samling for det

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- kilde til en anden enkel sløjfe kalder wibble 10 gange

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

nogle foregiver samling til denne sag

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 

noget mere c kilde

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

og samlingen

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

se hvor kort det er?

nogle flere c kilde

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

og samlingen (lad os antage en marginalt smart kompilator, der kan erstatte == 0 uden sammenligning )

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

Lad os nu prøve en konvention af true = 1

noget mere c kilde #definer SAND 1 int foo = SAND; hvis (foo == SAND) wibble ()

og forsamlingen

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

kan du se, hvor kort sagen med ikke-nul sand er?

Virkelig tidlige CPUer havde små sæt flag fastgjort til akkumulatoren.

At kontrollere, om a> b eller a = b generelt tager en sammenligningsinstruktion.

  • Medmindre B er enten ZERO – i hvilket tilfælde ZERO-flag er indstillet Implementeret som et simpelt logisk NOR eller alle bits i akkumulatoren.
  • Eller NEGATIV, hvor du bare bruger “tegnbit” dvs. den mest betydningsfulde bit i akkumulatoren hvis du bruger to “komplement aritmetik. (Det gør vi mest)

Lad os gentage dette. På nogle ældre CPUer behøvede du ikke bruge en sammenligningsinstruktion for akkumulator svarende til NUL eller akkumulator mindre end nul.

Ser du nu, hvorfor nul måske er falsk?

Bemærk venligst, at dette er psuedo-kode, og intet rigtigt instruktions sæt ser helt sådan ud. Hvis du kender samling, ved du, at jeg forenkler tingene meget her. Hvis du ved noget om kompilerdesign, behøvede du ikke at læse dette svar. Enhver, der ved noget om løkkeudrulning eller grenforudsigelse, den avancerede klasse er nede i gangen i rum 203.

Kommentarer

  • Dit punkt er ikke godt fremført her, for for det første if (foo) og if (foo != 0) skal generere den samme kode, og for det andet viser du ‘ at det samlingssprog, du ‘ faktisk bruger, har eksplicit boolske operander og test for dem. For eksempel betyder jz jump if zero. Med andre ord if (a == 0) goto target; Og mængden testes ikke engang direkte; betingelsen konverteres, det er et boolesk flag, der er gemt i et specielt maskinord. Det ‘ ligner faktisk cpu.flags.zero = (a == 0); if (cpu.flags.zero) goto target;
  • Nej Kaz, den ældre CPU ‘ s virkede ikke sådan. T he jz / jnz kan udføres uden at foretage en sammenligningsinstruktion. Hvilket virkelig var pointen med hele mit indlæg.
  • Jeg skrev ikke ‘ om en sammenligningsinstruktion.
  • Kan du citerer en processor, der har en jz instruktion, men ingen jnz? (eller ethvert andet asymmetrisk sæt betingede instruktioner)

Svar

Der er mange svar, der tyder på, at korrespondance mellem 1 og sand er nødvendig af en eller anden matematisk egenskab. Jeg kan ikke finde nogen sådan egenskab og foreslå, at det er en rent historisk konvention.

Givet et felt med to elementer, har vi to operationer: tilføjelse og multiplikation. Vi kan kortlægge boolske operationer på dette felt på to måder :

Traditionelt identificerer vi Sand med 1 og Falsk med 0. Vi identificerer OG med * og XOR med +. OR er således mættende tilføjelse.

Vi kunne dog lige så let identificer Sand med 0 og Falsk med 1. Så identificerer vi ELLER med * og XNOR med +. Således er AND en mættende tilføjelse.

Kommentarer

  • Hvis du havde fulgt linket på wikipedia, kunne du have fundet ud af, at begrebet boolsk algebra er lukket relateret til et Galois-felt med to elementer ( da.wikipedia.org/wiki / GF% 282% 29 ). Symbolerne 0 og 1 bruges traditionelt til at angive henholdsvis additiv og multiplikativ identitet, fordi de reelle tal også er et felt, hvis identitet er tallene 0 og 1.
  • @NeilG Jeg tror, Giorgio prøver at sige det ‘ er mere end bare en konvention. 0 og 1 i boolsk algebra er grundlæggende de samme som 0 og 1 i GF (2), som opfører sig næsten det samme som 0 og 1 i reelle tal med hensyn til tilføjelse og multiplikation.
  • @svick: Nej , fordi du simpelthen kan omdøbe multiplikation og mættende tilføjelse til at være OR og AND og derefter vende etiketterne, så 0 er sandt og 1 er falsk.Giorgio siger, at det var en konvention af boolsk logik, som blev vedtaget som en konvention inden for datalogi.
  • @Neil G: Nej, du kan ikke vende + og * og 0 og 1, fordi et felt kræver distribution af multiplikation over tilføjelse (se da.wikipedia.org/wiki/Field_%28mathematics%29 ), men hvis du indstiller +: = AND og *: = XOR får du T XOR (T OG F) = T XOR F = T, mens (T XOR T) OG (T XOR F) = F OG T = F. Derfor ved at vende operationerne og identiteterne har du ikke et felt mere. Så IMO, der definerer 0 og 1 som identiteterne i et passende felt, ser ud til at fange falsk og sand ret trofast.
  • @giorgio: Jeg har redigeret svaret for at gøre det indlysende, hvad der foregår.

Svar

Mærkeligt nok er nul ikke altid falsk.

Især Unix- og Posix-konventionen er at definere EXIT_SUCCESS som 0 (og EXIT_FAILURE som 1). Faktisk er det endda en standard C-konvention !

Så for Posix-skaller og exit (2) syscalls, 0 betyder “vellykket”, hvilket intuitivt er mere sandt end falsk.

Især skal shell “s if en proces returner EXIT_SUCCESS (dvs. 0) for at følge dens “derefter” gren!

I skema (men ikke i Common Lisp eller i MELT ) 0 og nul (dvs. () i skema) er sande, da den eneste falske værdi er #f

Jeg er enig, jeg kvæler!

Svar

C bruges til programmering på lavt niveau tæt på hardware, et område, hvor du nogle gange har brug for at skifte mellem bitvise og logiske operationer på de samme data. At være forpligtet til at konvertere et numerisk udtryk til boolsk bare for at udføre en test ville rod koden.

Du kan skrive ting som:

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

i stedet for

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

I et isoleret eksempel er det ikke så slemt, men at skulle gøre det bliver irriterende.

På samme måde skal du tale om operationer. Det er nyttigt for resultatet af en boolsk operation, som en sammenligning, at bare producere et 0 eller 1: Antag, at vi vil indstille den tredje bit af et ord baseret på, om modemctrl har bæreregistreringsbit:

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

Her skal vi have != 0, for at reducere resultatet af biwisen & udtryk til 0 eller 1, men fordi resultatet bare er et heltal, er vi skånet fra at skulle tilføje nogle irriterende rollebesætninger for yderligere at konvertere boolsk til heltal.

Selvom moderne C nu har en bool type, det bevarer stadig gyldigheden af kode som denne, både fordi den er en god ting, og på grund af den massive brud med bagudkompatibilitet, der ellers ville være forårsaget.

En anden exmaple, hvor C er glat: at teste to boolske forhold som en firevejs switch:

Du kunne ikke tage dette væk fra C-programmøren uden kamp!

Endelig serverer C undertiden som et slags samlingssprog på højt niveau. På samlingssprog har vi heller ikke boolske typer. En boolsk værdi er bare en smule eller en nul versus ikke-nul-værdi i en hukommelsesplacering eller et register. Et heltal nul, boolsk nul og adressen nul testes alle på samme måde i samlingssprogs instruktions sæt (og måske endda flydende punkt nul). Lighed mellem C og assemblingsprog er nyttigt, for eksempel når C bruges som målsprog til kompilering af et andet sprog (selv et der har stærkt skrevet booleans!)

Svar

En boolsk værdi eller sandhedsværdi har kun 2 værdier. Sandt og falsk.

Disse skal ikke vises som heltal, men som bits (0 og 1

At sige ethvert andet heltal ud for 0 eller 1 ikke er falsk er en forvirrende sætning. Sandhedstabeller beskæftiger sig med sandhedsværdier, ikke heltal.

Fra en sandhedsværdi er potentiel -1 eller 2, der bryder alle sandhedstabeller og enhver boolsk logik, der er tilknyttet dem.

  • 0 OG -1 ==?!
  • 0 ELLER 2 ==?!

De fleste sprog har normalt en boolean type, som når den kastes til en nummertype såsom heltal afslører falsk at blive kastet som en heltalværdi på 0.

Kommentarer

  • 0 OG -1 == uanset hvilken boolsk værdi du kaster dem til. At ‘ er hvad mit spørgsmål handler om, hvorfor kaste dem til TRUE eller FALSE.Aldrig sagde jeg – måske gjorde jeg det, men det var ikke meningen – heltal var sande eller falske, jeg spurgte, hvorfor de evaluerer til det, når de blev kastet til boolsk.

Svar

I sidste ende taler du om at bryde kernesproget, fordi nogle APIer er skøre. Crappy APIer er ikke nye, og du kan ikke rette dem ved at bryde sproget. Det er en matematisk kendsgerning, at 0 er falsk og 1 er sandt, og ethvert sprog, der ikke respekterer dette, er grundlæggende brudt. Trevejs sammenligningen er niche og har ingen forretning, der har resultatet konverteres implicit til bool, da det returnerer tre mulige resultater. De gamle C APIer har simpelthen frygtelig fejlhåndtering og er også hæmmet, fordi C ikke har de nødvendige sprogfunktioner for ikke at have forfærdelige grænseflader.

Bemærk, at jeg ikke siger det for sprog, der ikke har implicit heltal-> boolsk konvertering.

Kommentarer

  • ” Det er en matematisk kendsgerning, at 0 er falsk og 1 er sandt ” Erm.
  • Kan du citere en reference til din ” matematiske kendsgerning, at 0 er falsk og 1 er sandt “? Dit svar lyder farligt som en rant.
  • Det ‘ er ikke en matematisk kendsgerning, men det er ‘ en matematisk konvention siden det 19. århundrede.
  • Boolsk algebra er repræsenteret af et endeligt felt, hvor 0 og 1 er identitetselementerne for operationer, der ligner additon og multiplikation. Disse operationer er henholdsvis OR og AND. Faktisk er boolsk algebra skrevet som normal algebra, hvor sidestilling betegner AND, og + symbolet betegner OR. Så for eksempel betyder abc + a'b'c (a and b and c) or (a and (not b) and (not c)).

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *