Hvorfor er 0 falsk? (Norsk)

Dette spørsmålet kan høres dumt ut, men hvorfor vurderes 0 til false og hvilken som helst annen [heltall] verdi til true er det meste av programmeringsspråk?

Sammenligning av strenger

Siden spørsmålet virker som et litt for enkelt, vil jeg forklare meg litt mer: først og fremst kan det virke tydelig for enhver programmerer, men hvorfor ville det ikke være et programmeringsspråk – det kan faktisk være, men ikke noe jeg brukte – hvor 0 evalueres til true og alle de andre [heltall] verdiene til false? kan virke tilfeldig, men jeg har noen få eksempler der det kan ha vært en god idé. Først av alt, la oss ta eksemplet med strenges treveis sammenligning, jeg tar C «s strcmp som eksempel: enhver programmerer som prøver C som førstespråk, kan bli fristet til å skrive følgende kode:

Siden strcmp returnerer 0 som evalueres til false når strengene er like, mislykkes det begynnelsesprogrammereren forsøkte å gjøre, og han forstår generelt ikke hvorfor først. Hadde 0 evaluert til true i stedet, kunne denne funksjonen ha blitt brukt i sitt mest enkle uttrykk – det ovenfor – når man sammenligner for likhet, og de riktige kontrollene for -1 og 1 ville bare blitt gjort når det var nødvendig. Vi ville ha sett på returtypen som bool (i våre tanker mener jeg) mesteparten av tiden.

Dessuten, la oss introdusere en ny type, sign, som bare tar verdier -1, 0 og 1. Det kan være ganske praktisk. Tenk deg at det er en romskipoperatør i C ++, og vi vil ha den til std::string (vel, det er allerede compare -funksjonen, men romskipoperatør er morsommere). Erklæringen vil for tiden være den følgende:

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

Hadde 0 blitt evaluert til true, romskipoperatøren ville ikke engang eksistere, og vi kunne ha erklært operator== på den måten:

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

Denne operator== ville har håndtert treveis sammenligning samtidig, og kan fortsatt brukes til å utføre følgende kontroll mens du fremdeles kan sjekke hvilken streng som er leksikografisk overlegen den andre når det er nødvendig:

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

Gamle feilhåndtering

Vi har nå unntak, så denne delen gjelder bare for de gamle språkene der ingen slike ting eksisterer (for eksempel C). Hvis vi ser på C «s standardbibliotek (og POSIX også), kan vi med sikkerhet se at maaaaany-funksjoner returnerer 0 når det lykkes og ellers et heltall. Jeg har dessverre sett noen mennesker gjør denne typen ting:

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

Hvis vi tenker på hvordan vi tenker i programmering har vi ofte følgende resonnementsmønster:

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

Hvis vi tenker på det igjen, ville det vært fornuftig å sette den eneste nøytrale verdien, 0, til yes (og det er slik C «s funksjoner fungerer), mens alle de andre verdiene kan være der for å løse de mange tilfellene av no. Imidlertid, i alle programmeringsspråkene jeg kjenner (bortsett fra kanskje noen eksperimentelle esoteriske språk), som yes evalueres til false i en if -tilstand, wh ile alle no -sakene evalueres til true. Det er mange situasjoner når «det fungerer» representerer ett tilfelle mens «det virker ikke» representerer mange sannsynlige årsaker. Hvis vi tenker på det slik, å ha 0 evaluere til true og resten til false ville ha gjort mye mer fornuftig.

Konklusjon

Min konklusjon er egentlig mitt originale spørsmål: hvorfor designet vi språk der 0 false og de andre verdiene er true, med tanke på mine få eksempler ovenfor og kanskje noen flere jeg ikke tenkte på?

Oppfølging: Det er hyggelig å se at det er mange svar med mange ideer og så mange mulige grunner for at det skal være sånn. Jeg elsker hvor lidenskapelig du ser ut til å være om det.Jeg spurte opprinnelig dette spørsmålet ut av kjedsomhet, men siden du virker så lidenskapelig, bestemte jeg meg for å gå litt lenger og spørre om begrunnelsen bak det boolske valget for 0 og 1 på Math.SE 🙂

Kommentarer

  • strcmp() er ikke noe godt eksempel for sant eller false, da den returnerer 3 forskjellige verdier. Og du vil bli overrasket når du begynner å bruke et skall, der 0 betyr sant og alt annet betyr usant.
  • @ ott–: I Unix-skjell betyr 0 suksess og ikke -null betyr feil – ikke helt det samme som » true » og » false «.
  • @KeithThompson: I Bash (og andre skjell), » suksess » og » feil » er virkelig det samme som » true » og » false «. Tenk for eksempel påstanden if true ; then ... ; fi, der true er en kommando som returnerer null og dette forteller if for å kjøre ....
  • Det er ingen booleaner i maskinvare overhodet, bare binære tall, og i de fleste historiske ISAs anses et tall som ikke er null som » true » i alle de betingede forgreningsinstruksjonene (med mindre de ‘ bruker flagg i stedet). Så språkene på lavt nivå er for all del forpliktet til å følge de underliggende maskinvareegenskapene.
  • @MasonWheeler Å ha en boolsk type betyr ikke ‘ t. For eksempel har python en bool -type, men sammenligninger / hvis forhold osv. Kan ha en hvilken som helst returverdi.

Svar

0 er false fordi de begge er null elementer til felles semirings . Selv om de er forskjellige datatyper, er det intuitivt fornuftig å konvertere mellom dem fordi de tilhører isomorfe algebraiske strukturer.

  • 0 er identiteten for tillegg og null for multiplikasjon. Dette gjelder heltall og rasjonelle, men ikke IEEE-754 flytende tall: 0.0 * NaN = NaN og 0.0 * Infinity = NaN .

  • false er identiteten til boolsk xor (⊻) og null for boolsk og (∧). Hvis booleans er representert som {0, 1} – settet med heltall modulo 2, kan du tenke på ⊻ som tillegg uten bære og ∧ som multiplikasjon.

  • "" og [] er identitet for sammenkobling, men det er flere operasjoner som de gir mening som null. Gjentagelse er en, men repetisjon og sammenkobling distribuerer ikke, så disse operasjonene danner ikke en semiring.

Slike implisitte konverteringer er nyttige i små programmer, men i store kan gjøre programmer vanskeligere å resonnere om. Bare en av de mange kompromissene innen språkdesign.

Kommentarer

  • Hyggelig at du nevnte lister. (BTW, nil er både den tomme listen [] og false -verdien i Common Lisp ; er det en tendens til å slå sammen identiteter fra forskjellige datatyper?) Du må fortsatt forklare hvorfor det er naturlig å betrakte falsk som en additiv identitet og sann som en multiplikativ identitet og ikke omvendt. Er det ikke ‘ t å anse true som identifikasjonen for AND og null for OR?
  • +1 for å referere til lignende identiteter. Til slutt et svar som ikke ‘ t bare koker ned til » konvensjon, takler det «.
  • +1 for å gi detaljer om en konkret og veldig gammel matematikk der dette har blitt fulgt og lenge har gitt mening
  • Dette svaret ‘ t gir mening. true er også identiteten og null av semiringer (boolsk og / eller). Det er ingen grunn, appart-konvensjonen, til å vurdere false er nærmere 0 enn true.
  • @TonioElGringo: Forskjellen mellom sant og usant er forskjellen mellom XOR og XNOR. Man kan danne isomorfe ringer ved å bruke AND / XOR, hvor sant er multiplikativ identitet og falsk tilsetningsstoff, eller med OR og XNOR, hvor falsk er multiplikasjonsidentitet og sant er additiv, men XNOR blir vanligvis ikke sett på som en vanlig grunnleggende operasjon slik XOR er.

Svar

Fordi matematikken fungerer.

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

Tradisjonelt har C-programmer forhold som

 if (someFunctionReturningANumber())  

i stedet for

 if (someFunctionReturningANumber() != 0)  

fordi begrepet null tilsvarer falsk er godt forstått.

Kommentarer

  • Språkene er utformet slik fordi matematikken er fornuftig. Det kom først.
  • @Morwenn, det går tilbake til 1800-tallet og George Boole. Folk har representert False som 0 og True as! 0 lenger enn det har vært datamaskiner.
  • Jeg ser ikke ‘ hvorfor matematikken ikke ‘ t fungerer den andre veien hvis du bare endrer alle definisjonene slik at AND er + og OR er *.
  • Nøyaktig: matematikken fungerer begge veier og svaret på dette spørsmålet ser ut til å være at det er rent konvensjonelt.
  • @Robert Det ‘ d være bra hvis du kunne stave ut » matematiske underlag » i innlegget ditt.

Svar

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

Hvilken matte snakker vi om? Boolske algebraer som stammer fra midten av 1800-tallet, lenge før digitale datamaskiner kom.

Du kan også si at konvensjonen kom ut av proposisjonslogikk , som enda eldre enn boolske algebraer. Dette er formaliseringen av mange av de logiske resultatene som programmerere kjenner og elsker (false || x tilsvarer x, true && x er lik x og så videre).

I utgangspunktet snakker vi om aritmetikk på et sett med to elementer. Tenk på å telle i binær. Boolske algebraer er opprinnelsen til dette konseptet og dets teoretiske grunnlag. Konvensjonene av språk som C er bare en enkel applikasjon.

Kommentarer

  • Du kan , helt sikkert. Men å holde det på » standard » passer godt inn i generell regning (0 + 1 = 1, ikke 0 + 1 = 0).
  • Ja, men du vil antagelig skrive OG med + og ELLER med * hvis du også reverserte definisjonene.
  • Matematikken gjorde ikke ‘ kommer ikke først. Matematikk anerkjente at 0 og 1 danner et felt der AND er som multiplikasjon og OR er som tillegg.
  • @ Kaz: Men {0, 1} med OR og AND danner ikke et felt.
  • Det plager meg litt at flere svar og kommentarer sier at true = 1. At ‘ ikke er helt nøyaktig, fordi true != 0 som ikke er akkurat det samme. Én grunn (ikke den eneste) til at man bør unngå sammenligninger som if(something == true) { ... }.

Svar

Jeg trodde dette hadde å gjøre med «arven» fra elektronikk, og også boolsk algebra, der

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

strcmp returnerer 0 når strengene er like har å gjøre med implementeringen, siden det den faktisk gjør er å beregne «avstanden» mellom de to strengene. At 0 også blir ansett som falsk, er bare en tilfeldighet.

Å returnere 0 på suksess gir mening fordi 0 i dette tilfellet brukes til å bety ingen feil og ethvert annet nummer vil være en feilkode. Å bruke et hvilket som helst annet tall for å lykkes ville være mindre fornuftig, siden du bare har en enkelt suksesskode, mens du kan ha flere feilkoder. Du bruker «Fungerte det?» som if-setningsuttrykket og si 0 = ja ville være mer fornuftig, men uttrykket er mer korrekt «Gjorde noe galt?» og så ser du at 0 = nei gir mye mening. Å tenke på false/true gir ingen mening her, da det faktisk er no error code/error code.

Kommentarer

  • Haha, du er den første til å oppgi returfeilspørsmålet eksplisitt. Jeg visste allerede at jeg tolket det på min egen måte, og det kunne jeg spørre den andre veien, men du ‘ er den første som eksplisitt uttrykker det (av de mange svarene og kommentarene).Egentlig ville jeg ikke ‘ ikke si at den ene eller andre veien ikke gir mening, men mer at begge gir mening på forskjellige måter 🙂
  • Egentlig jeg ‘ d si 0 for success/no error er det eneste som gir mening når andre heltall representerer feilkoder . At 0 tilfeldigvis også representerer false i andre tilfeller betyr ikke ‘ t noe, siden vi snakker ‘ t i det hele tatt om sant eller usant;)
  • Jeg hadde den samme ideen, så jeg oppdro
  • Ditt poeng om strcmp() Det er ganske bra å beregne avstanden. Hvis det hadde blitt kalt strdiff(), ville if (!strdiff()) være veldig logisk.
  • » elektronikk […] der 0 = […] false, 1 = […] true » – selv i elektronikk er dette bare en konvensjon , og er ikke ‘ t den eneste. Vi kaller dette positiv logikk, men du kan også bruke negativ logikk, der en positiv spenning indikerer falsk og negativ indikerer sann. Deretter blir kretsen du ‘ bruker for AND ELLER OR, ELLER blir AND, og så videre. På grunn av De Morgan ‘ lov, ender det hele opp med å være ekvivalent. Noen ganger finner du ‘ en del av en elektronisk krets implementert i negativ logikk for enkelhets skyld, på hvilket tidspunkt navnene på signalene i den delen er notert med en stolpe over dem.

Svar

Som forklart i denne artikkelen , verdiene false og true skal ikke forveksles med heltallene 0 og 1, men kan identifiseres med elementene i Galois-feltet (endelig felt) av to elementer (se her ).

Et felt er et sett med to operasjoner som tilfredsstiller visse aksiomer.

Symbolene 0 og 1 brukes konvensjonelt for å betegne additiv- og multiplikasjonsidentitetene til et felt fordi de reelle tallene også er et felt (men ikke et endelig felt) hvis identitet er tallene 0 og 1.

Additividentiteten er elementet 0 i feltet, slik at for alle x:

x + 0 = 0 + x = x 

og den multiplikative identiteten er elementet 1 i feltet, slik at for alle x:

x * 1 = 1 * x = x 

Det endelige feltet av to elementer har bare disse to elementene, nemlig additiv identitet 0 (eller false), og multiplikasjonsidentiteten 1 (eller true). De to operasjonene i dette feltet er den logiske XOR (+) og den logiske AND (*).

Merk. Hvis du snur operasjonene (XOR er multiplikasjon og AND er tillegg), så er multiplikasjonen ikke distribuerende over addisjon, og du har ikke noe felt lenger. I et slikt tilfelle har du ingen grunn til å kalle de to elementene 0 og 1 (i hvilken som helst rekkefølge). Vær også oppmerksom på at du ikke kan velge operasjonen ELLER i stedet for XOR: uansett hvordan du tolker OR / AND som tillegg / multiplikasjon, er den resulterende strukturen ikke et felt (ikke alle inverse elementer eksisterer slik feltaksiomene krever). >

Når det gjelder C-funksjonene:

  • Mange funksjoner returnerer et heltall som er en feilkode. 0 betyr INGEN FEIL.
  • Intuitivt beregner funksjonen strcmp forskjellen mellom to strenger. 0 betyr at det ikke er noen forskjell mellom to strenger, dvs. at to strenger er like.

Ovennevnte intuitive forklaringer kan bidra til å huske tolkningen av returverdiene, men det er enda enklere å det er bare å sjekke dokumentasjonen til biblioteket.

Kommentarer

  • +1 for å vise at hvis du vil bytte disse vil matematikken ikke lenger fungere.
  • Vendt: Gitt et felt med to elementer og operasjoner * og +, identifiserer vi True med 0 og False med 1. Vi identifiserer OR med * og XOR med +.
  • Du vil finne at begge av disse identifikasjonene gjøres over samme felt, og begge er i samsvar med reglene for boolsk logikk. Merknaden din er dessverre feil 🙂
  • Hvis du antar at True = 0, og XOR er +, må True være identiteten til XOR. Men det er ikke fordi True XOR True = False. Med mindre du omdefinerer operasjonen XOR på True slik at True XOR True = True. Så selvfølgelig fungerer konstruksjonen fordi du nettopp har omdøpt ting (i en hvilken som helst matematisk struktur kan du alltid lykkes med å lage et navn permutasjon og få en isomorf struktur). På den annen side, hvis du lar True, False og XOR ha sin vanlige betydning, så kan True XOR True = False and True ikke være additividentiteten, dvs. True kan ikke være 0.
  • @Giorgio: Jeg korrigerte konstruksjonen min i henhold til kommentaren din i min siste kommentar …

Svar

Du bør vurdere at alternative systemer også kan være akseptable designbeslutninger.

Skjell: 0 utgangsstatus er sant, ikke-null er usant

Eksemplet på skjell som behandler en 0 utgangsstatus som sant er allerede nevnt.

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

Begrunnelsen der er at det er en måte å lykkes på, men mange måter å mislykkes på, så det er pragmatisk å bruke 0 som den spesielle verdien som betyr «ingen feil».

Ruby: 0 er akkurat som alle andre tall

Blant «normale» programmeringsspråk er det noen outliers, for eksempel Ruby, som behandler 0 som en sann verdi.

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

begrunnelsen er at bare false og nil skal være falske. For mange Ruby-nybegynnere er det «sa gotcha. I noen tilfeller er det fint at 0 behandles akkurat som ethvert annet 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" 

Imidlertid , fungerer et slikt system bare på et språk som er i stand til å skille boolere som en egen type fra tall. Tidligere i databehandlingen hadde programmerere som jobbet med monteringsspråk eller rå maskinspråk ingen slik luksus. Det er sannsynligvis bare naturlig å behandle 0 som «blank» tilstand, og sette litt til 1 som et flagg når koden oppdaget at noe skjedde. I forlengelsen utviklet konvensjonen at null ble behandlet som falsk, og ikke-nullverdier ble behandlet som sanne. Det trenger imidlertid ikke være slik.

Java: Tall kan ikke behandles som booleans i det hele tatt

I Java, true og false er de eneste boolske verdiene. Tall er ikke booleanske, og kan ikke engang kastes til booleanere ( Java Language Specification, Sec 4.2.2 ):

Det er ingen rollebesetninger mellom integrerte typer og typen boolean .

Denne regelen unngår bare spørsmålet helt – alle boolske uttrykk må skrives eksplisitt i koden.

Kommentarer

  • Rebol og Red behandler begge 0-verdsatte INTEGER! -verdier som sanne, og har en egen INGEN! -type (med bare én verdi, INGEN) behandlet som betinget falsk i tillegg til LOGIC! false. Jeg ‘ har funnet betydelig frustrasjon i å prøve å skrive JavaScript-kode som behandler 0 som falsk; det er en inkr spiselig klønete beslutning for et dynamisk skrevet språk. Hvis du vil teste noe som kan være null eller 0, slutter du å måtte skrive if (thing === 0), det er bare ikke kult.
  • @HostileFork gjør jeg ikke ‘ vet ikke. Jeg finner ut at det er fornuftig at 0 er true (som hvert annet heltall) på et dynamisk språk. Jeg tilfeldigvis fanget en 0 når jeg prøvde å fange None i Python, og det kan noen ganger være ganske vanskelig å få øye på.
  • Ruby er ikke en outlier. Ruby tar dette fra Lisp (Ruby kalles til og med i hemmelighet » MatzLisp «). Lisp er et vanlig språk innen informatikk. Null er også bare en sann verdi i POSIX-skallet, fordi det ‘ er et stykke tekst: if [ 0 ] ; then echo this executes ; fi. Den falske dataværdien er en tom streng, og en testbar usannhet er en mislykket avslutningsstatus for en kommando, som er representert med en non -null.

Svar

Før vi behandler den generelle saken, kan vi diskutere moteksemplene dine.

Sammenligninger av strenger

Det samme gjelder faktisk for mange slags sammenligninger. Slike sammenligninger beregner en avstand mellom to objekter. Når gjenstandene er like, er avstanden minimal. Så når «sammenligningen lykkes», er verdien 0. Men egentlig er returverdien av strcmp ikke en boolsk, det er en avstand, og at det som feller uvitende programmerere som gjør if (strcmp(...)) do_when_equal() else do_when_not_equal().

I C ++ kan vi redesigne strcmp for å returnere en Distance objekt, som overstyrer operator bool() for å returnere true når 0 (men du vil da bli bitt av et annet sett med problemer). Eller bare ha bare en streq -funksjon som returnerer 1 når strengene er like, og 0 ellers.

API-anrop / programutgangskode

Her bryr du deg om årsaken til at noe gikk galt, fordi dette vil føre beslutningene til feil. Når ting lykkes, vil du ikke vite noe spesielt – intensjonen din blir realisert. Returverdien må derfor formidle denne informasjonen.Det er ikke en boolsk, det er en feilkode. Den spesielle feilverdien 0 betyr «ingen feil». Resten av området representerer lokalt meningsfylte feil du må forholde deg til (inkludert 1, som ofte betyr «uspesifisert feil»).

Generelt tilfelle

Dette etterlater oss med spørsmålet: hvorfor er boolske verdier True og False ofte representert med henholdsvis 1 og 0?

Vel, i tillegg til det subjektive «det føles bedre på denne måten» argumentet, er det noen få grunner (også subjektive) jeg kan tenke på:

  • analogi for elektrisk krets. Strømmen er PÅ i 1s, og OFF for 0s. Jeg liker å ha (1, Ja, Sann, På) sammen, og (0, Nei, Falsk, Av), i stedet for en annen blanding

  • minneinitialiseringer. Når jeg memset(0) en haug med variabler (det være seg ints, floats, bools), vil jeg at verdien skal matche de mest konservative antagelsene. F.eks. summen min er opprinnelig 0, predikatet er falsk osv.

Kanskje alle disse grunnene er knyttet til utdannelsen min – hvis jeg hadde blitt lært å knytte 0 til True fra begynnelsen, ville jeg gått omvendt.

Kommentarer

  • Egentlig er det minst ett programmeringsspråk som behandler 0 som sant. Unix-skallet.
  • +1 for å løse det virkelige problemet: De fleste av Morwenn ‘ spørsmål er ikke ‘ t om bool i det hele tatt.
  • @ dan04 Det er det. Hele innlegget handler om begrunnelsen bak valget av rollebesetningen fra int til bool på mange programmeringsspråk. Sammenligning og feil gestion ting er bare eksempler på steder der det kan være fornuftig å kaste det på en annen måte enn det det ‘ gjør for øyeblikket.

Svar

Fra et høyt nivåperspektiv snakker du om tre ganske forskjellige datatyper:

  1. En boolsk. Den matematiske konvensjonen i Boolsk algebra er å bruke 0 for false og 1 for true, så det er fornuftig å følge den konvensjonen. Jeg tror denne måten også gir mer mening intuitivt.

  2. Resultatet av sammenligningen. Dette har tre verdier: <, = og > (legg merke til at ingen av dem er true). For dem er det fornuftig å bruke verdiene henholdsvis -1, 0 og 1 (eller, mer generelt, en negativ verdi, null og en positiv verdi).

    Hvis du vil sjekke om det er likestilling a Hvis du bare har en funksjon som utfører generell sammenligning, tror jeg du bør gjøre det eksplisitt ved å bruke noe som strcmp(str1, str2) == 0. Jeg synes det er forvirrende å bruke ! i denne situasjonen, fordi det behandler en ikke-boolsk verdi som om det var en boolsk.

    Husk også at sammenligning og likestilling trenger ikke å være den samme. Hvis du for eksempel bestiller folk etter fødselsdatoen, skal Compare(me, myTwin) returnere 0 , men Equals(me, myTwin) skal returnere false.

  3. Suksessen eller feilen til en funksjon , muligens også med detaljer om suksessen eller fiaskoen. Hvis du snakker om Windows, kalles denne typen HRESULT og en ikke-nullverdi indikerer ikke nødvendigvis feil. Faktisk indikerer en negativ verdi feil og ikke-negativ suksess. Suksessverdien er veldig ofte S_OK = 0, men det kan også være for eksempel S_FALSE = 1, eller andre verdier.

Forvirringen kommer av det faktum det tre logisk ganske forskjellige datatyper er faktisk representert som en enkelt datatype (et heltall) i C og noen andre språk, og at du kan bruke heltall i en tilstand. Men jeg tror ikke det vil være fornuftig å omdefinere boolsk for å gjøre det å bruke noen ikke-boolske typer under forhold som er enklere.

Vurder også en annen type som ofte brukes i en tilstand i C: en peker . Der er det naturlig å behandle en NULL -peker (som er representert som 0) som false. Så hvis du følger ditt forslag, vil det også gjøre det vanskeligere å jobbe med pekere. (Selv om jeg personlig foretrekker å sammenligne pekere med NULL, i stedet for å behandle dem som booleans.)

Svar

Null kan være falsk fordi de fleste CPU-er har ZERO-flagg som kan brukes til å forgrene seg. Det sparer en sammenligningsoperasjon.

La oss se hvorfor.

Noen psuedokoder, ettersom publikum sannsynligvis ikke leser montering

c- kilde enkle sløyfe kaller wibble 10 ganger

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

noen later til forsamling 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 annen enkel sløyfesamtaler wibble 10 ganger

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

noen later til montering for denne saken

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 

litt mer c kilde

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

og forsamlingen

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

se hvor kort det er?

litt mer c kilde

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

og forsamlingen (kan anta en marginalt smart kompilator som kan erstatte == 0 uten sammenligning )

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

Nå kan vi prøve en konvensjon av true = 1

litt mer c kilde #definere SANN 1 int foo = SANN; hvis (foo == SANT) wibble ()

og forsamlingen

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

ser du hvor kort saken med ikke-null sant er?

Virkelig tidlige CPU-er hadde små sett med flagg festet til akkumulatoren.

For å sjekke om a> b eller a = b generelt tar en sammenligningsinstruksjon.

  • Med mindre B er enten ZERO – i hvilket tilfelle ZERO-flagget er satt Implementert som et enkelt logisk NOR eller alle biter i akkumulatoren.
  • Eller NEGATIV der du bare bruker «sign-bit» dvs. den viktigste biten av akkumulatoren hvis du bruker to «komplement aritmetikk. (For det meste gjør vi det)

La oss gjenta dette. På noen eldre CPU-er måtte du ikke bruke en sammenligningsinstruksjon for akkumulator lik ZERO, eller akkumulator mindre enn null.

Ser du hvorfor null kan være falsk?

Vær oppmerksom på at dette er psuedo-kode og ingen reelle instruksjonssett ser ganske slik ut. Hvis du vet montering, vet du at jeg forenkler ting mye her. Hvis du vet noe om kompilerdesign, trengte du ikke å lese dette svaret. Alle som vet noe om løkkeutrulling eller forutsigelse av grener, den avanserte klassen er nede i gangen i rom 203.

Kommentarer

  • Poenget ditt er ikke godt fremført her fordi for en ting if (foo) og if (foo != 0) skal generere den samme koden, og for det andre viser du ‘ at samlingsspråket du ‘ faktisk bruker, har eksplisitt boolske operander og tester for dem. For eksempel betyr jz jump if zero. Med andre ord if (a == 0) goto target; … Og mengden blir ikke engang testet direkte, tilstanden blir konvertert til et boolesk flagg som er lagret i et spesielt maskinord. Det ‘ ligner faktisk mer på cpu.flags.zero = (a == 0); if (cpu.flags.zero) goto target;
  • Nei Kaz, den eldre CPU ‘ s fungerte ikke slik. T he jz / jnz kan utføres uten å gjøre en sammenligningsinstruksjon. Som egentlig var poenget med hele innlegget mitt.
  • Jeg skrev ikke ‘ om en sammenligningsinstruksjon.
  • Kan du sitere en prosessor som har en jz instruksjon, men ingen jnz? (eller ethvert annet asymmetrisk sett med betingede instruksjoner)

Svar

Det er mange svar som tyder på at samsvar mellom 1 og sant er nødvendig av noen matematiske egenskaper. Jeg kan ikke finne noen slik egenskap og foreslå at det er en rent historisk konvensjon.

Gitt et felt med to elementer, har vi to operasjoner: addisjon og multiplikasjon. Vi kan kartlegge boolske operasjoner på dette feltet på to måter :

Tradisjonelt identifiserer vi True med 1 og False med 0. Vi identifiserer AND med * og XOR med +. Dermed er OR mettende tillegg.

Vi kunne imidlertid like gjerne identifisere True med 0 og False med 1. Så identifiserer vi OR med * og XNOR med +. Dermed er AND mettende tillegg.

Kommentarer

  • Hvis du hadde fulgt lenken på wikipedia, du kunne ha funnet ut at begrepet boolsk algebra er lukket relatert til begrepet Galois-felt med to elementer ( en.wikipedia.org/wiki / GF% 282% 29 ). Symbolene 0 og 1 brukes konvensjonelt for å betegne henholdsvis additiv og multiplikasjonsidentitet, fordi de reelle tallene også er et felt hvis identitet er tallene 0 og 1.
  • @NeilG Jeg tror Giorgio prøver å si det ‘ er mer enn bare en konvensjon. 0 og 1 i boolsk algebra er i utgangspunktet de samme som 0 og 1 i GF (2), som oppfører seg nesten det samme som 0 og 1 i reelle tall med hensyn til tillegg og multiplikasjon.
  • @svick: Nei fordi du ganske enkelt kan endre navn på multiplikasjon og metningstilsetning til å være OR og AND og deretter snu etikettene slik at 0 er sant og 1 er usant.Giorgio sier at det var en konvensjon av boolsk logikk, som ble vedtatt som en datavitenskapskonvensjon.
  • @Neil G: Nei, du kan ikke snu + og * og 0 og 1 fordi et felt krever distribusjon av multiplikasjon over tillegg (se en.wikipedia.org/wiki/Field_%28mathematics%29 ), men hvis du angir +: = 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 å snu operasjonene og identitetene, har du ikke et felt lenger. Så IMO som definerer 0 og 1 som identitetene til et passende felt ser ut til å fange falskt og sant ganske trofast.
  • @giorgio: Jeg har redigert svaret for å gjøre det åpenbart hva som skjer.

Svar

Merkelig, null er ikke alltid falsk.

Spesielt Unix- og Posix-konvensjonen er å definere EXIT_SUCCESS som 0 (og EXIT_FAILURE som 1). Egentlig er det til og med en standard C-konvensjon !

Så for Posix-skjell og exit (2) syscalls, 0 betyr «vellykket» som intuitivt er mer sant enn usant.

Spesielt skal skallet «s if prosess returner EXIT_SUCCESS (altså 0) for å følge «da» -grenen!

I skjemaet (men ikke i Common Lisp eller i MELT ) 0 og null (dvs. () i skjema) er sanne, siden den eneste falske verdien er #f

Jeg er enig, jeg klikker!

Svar

C brukes til programmering på lavt nivå nær maskinvare, et område der du noen ganger trenger å skifte mellom bitvise og logiske operasjoner på de samme dataene. Å være påkrevd for å konvertere et numerisk uttrykk til boolsk bare for å utføre en test, ville være rot 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 isolert eksempel er det ikke så ille, men å måtte gjøre det blir irriterende.

Likeledes snakk operasjoner. Det er nyttig for resultatet av en boolsk operasjon, som en sammenligning, å bare produsere et 0 eller 1: Anta at vi vil sette den tredje biten av et ord basert på om modemctrl har transportøroppdagingsbit:

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

Her må vi ha != 0, for å redusere resultatet av biwise & uttrykk til 0 eller 1, men fordi resultatet bare er et heltall, er vi spart fra å måtte legge til noen irriterende rollebesetning for å konvertere boolsk til heltall ytterligere.

Selv om moderne C nå har en bool type, den bevarer fremdeles gyldigheten av koden som denne, både fordi den er en god ting, og på grunn av den massive brudd med bakoverkompatibilitet som ellers ville blitt forårsaket.

p> Et annet eksempel der C er glatt: å teste to boolske forhold som en fireveisbryter:

Du kunne ikke ta dette fra C-programmereren uten kamp!

Til slutt serverer C noen ganger som et slags monteringsspråk på høyt nivå. På monteringsspråk har vi heller ikke boolske typer. En boolsk verdi er bare en bit eller en null versus ikke-null verdi i et minneplassering eller register. Et helt tall null, boolsk null og adressen null blir alle testet på samme måte i instruksjonssett for monteringsspråk (og til og med flytende punkt null). Likhet mellom C og monteringsspråk er nyttig, for eksempel når C brukes som målspråk for å kompilere et annet språk (til og med et som har skrevet typiske booleanere!)

Svar

En boolsk eller sannhetsverdi har bare to verdier. Sann og usann.

Disse skal ikke representeres som heltall, men som biter (0 og 1

Å si noe annet heltall ved siden av 0 eller 1 er ikke falskt, er en forvirrende uttalelse. Sannhetstabeller håndterer sannhetsverdier, ikke heltall.

Fra en sannhetsverdi potensiell vil -1 eller 2 bryte alle sannhetstabeller og enhver boolsk logikk assosiert med dem.

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

De fleste språk har vanligvis en boolean type som når den kastes til en talltype slik som heltall, avslører at falsk skal kastes som en heltallsverdi på 0.

Kommentarer

  • 0 OG -1 == hvilken boolsk verdi du kaster dem til. At ‘ er hva spørsmålet mitt handler om, hvorfor kaste dem til TRUE eller FALSE.Aldri sa jeg – kanskje jeg gjorde det, men det var ikke meningen – heltall var sanne eller falske, jeg spurte om hvorfor de vurderer hva som helst når de ble kastet til boolsk.

Svar

Til slutt snakker du om å bryte kjernespråket fordi noen API-er er skitete. Crappy API-er er ikke nye, og du kan ikke fikse dem ved å bryte språket. Det er et matematisk faktum at 0 er usant og 1 er sant, og ethvert språk som ikke respekterer dette er fundamentalt ødelagt. Treveis sammenligningen er nisje og har ingen virksomhet som har resultatet som konverteres implisitt til bool siden det gir tre mulige resultater. De gamle C API-ene har ganske enkelt forferdelig feilhåndtering, og blir også hindret fordi C ikke har de nødvendige språkfunksjonene for ikke å ha forferdelige grensesnitt.

Merk at jeg ikke sier det for språk som ikke har implisitte heltall-> boolsk konvertering.

Kommentarer

  • » Det er et matematisk faktum at 0 er falsk og 1 er sant » Erm.
  • Kan du sitere en referanse for » matematisk faktum at 0 er falsk og 1 er sant «? Svaret ditt høres farlig ut som en rant.
  • Det ‘ er ikke et matematisk faktum, men det ‘ har vært en matematisk konvensjon siden 1800-tallet.
  • Boolsk algebra er representert med et endelig felt der 0 og 1 er identitetselementene for operasjoner som ligner additon og multiplikasjon. Disse operasjonene er henholdsvis OR og AND. Faktisk skrives boolsk algebra omtrent som normal algebra der sidestilling betegner AND, og + symbolet betegner OR. Så for eksempel betyr abc + a'b'c (a and b and c) or (a and (not b) and (not c)).

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *