Ondertekende versus niet-ondertekende gehele getallen

Heb ik gelijk als ik zeg dat het verschil tussen een geheel getal met en zonder teken het volgende is:

  1. Niet-ondertekend kan een grotere positieve waarde hebben en geen negatieve waarde.
  2. Unsigned gebruikt de leidende bit als onderdeel van de waarde, terwijl de ondertekende versie de meest linkse bit gebruikt om te bepalen of het getal positief of negatief is.
  3. Getekende gehele getallen kunnen zowel positieve als negatieve getallen bevatten.

Andere verschillen?


Antwoord 1, autoriteit 100%

Niet-ondertekend kan een grotere positieve waarde hebben en geen negatieve waarde.

Ja.

Unsigned gebruikt de leidende bit als onderdeel van de waarde, terwijl de ondertekende versie de meest linkse bit gebruikt om te bepalen of het getal positief of negatief is.

Er zijn verschillende manieren om getekende gehele getallen weer te geven. Het gemakkelijkst te visualiseren is om het meest linkse bit als vlag te gebruiken (teken en grootte), maar gebruikelijker is twee-complement. Beide worden gebruikt in de meeste moderne microprocessors: drijvende komma gebruikt teken en grootte, terwijl rekenen met gehele getallen het complement van twee gebruikt.

Getekende gehele getallen kunnen zowel positieve als negatieve getallen bevatten.

Ja.


Antwoord 2, autoriteit 26%

Ik ga in op verschillen op hardwareniveau, op x86. Dit is meestal niet relevant, tenzij je een compiler schrijft of assembler gebruikt. Maar het is leuk om te weten.

Ten eerste heeft x86 nativeondersteuning voor de two’s complementrepresentatie van getekende nummers. U kunt andere weergaven gebruiken, maar dit vereist meer instructies en is over het algemeen een verspilling van processortijd.

Wat bedoel ik met ‘native support’? In feite bedoel ik dat er een reeks instructies is die u gebruikt voor niet-ondertekende nummers en een andere reeks die u gebruikt voor ondertekende nummers. Niet-ondertekende nummers kunnen in dezelfde registers zitten als ondertekende nummers, en u kunt inderdaad ondertekende en niet-ondertekende instructies door elkaar halen zonder dat u zich zorgen hoeft te maken over de processor. Het is aan de compiler (of assemblageprogrammeur) om bij te houden of een nummer is ondertekend of niet, en de juiste instructies te gebruiken.

Ten eerste hebben twee-complementgetallen de eigenschap dat optellen en aftrekken precies hetzelfde is als voor niet-ondertekende getallen. Het maakt niet uit of de cijfers positief of negatief zijn. (Dus ga je gang en ADDen SUBje nummers zonder je zorgen te maken.)

De verschillen beginnen zichtbaar te worden als het gaat om vergelijkingen. x86 heeft een eenvoudige manier om ze te onderscheiden: boven/beneden geeft een vergelijking zonder teken aan en groter/kleiner dan geeft een vergelijking met teken aan. (Bijvoorbeeld JAEbetekent “Springen indien hoger of gelijk” en is niet ondertekend.)

Er zijn ook twee sets instructies voor vermenigvuldigen en delen voor het omgaan met getekende en niet-ondertekende gehele getallen.

Ten slotte: als u wilt controleren op bijvoorbeeld overloop, zou u het anders doen voor ondertekende en niet-ondertekende nummers.


Antwoord 3, autoriteit 20%

Hij vroeg alleen naar ondertekend en niet-ondertekend. Snap niet waarom mensen hier extra dingen aan toevoegen. Laat me je het antwoord vertellen.

  1. Niet ondertekend: het bestaat alleen uit niet-negatieve waarden, d.w.z. 0 tot 255.

  2. Ondertekend: het bestaat uit zowel negatieve als positieve waarden, maar in verschillende indelingen zoals

    • 0 tot +127
    • -1 tot -128

en deze uitleg gaat over het 8-bits nummersysteem.


4, Autoriteit 5%

slechts een paar punten voor volledigheid:

  • Dit antwoord besprak alleen gehele getal-representaties. Er kunnen andere antwoorden zijn voor zwevend punt;

  • De weergave van een negatief getal kan variëren. De meest voorkomende (veruit – het is vandaag bijna universeel) in gebruik vandaag is Two’s complement . Andere vertegenwoordigingen zijn onder meer One’s complement (vrij zeldzaam) en ondertekende magnitude (verdwijnend zeldzaam – waarschijnlijk alleen gebruikt op museumstukken) die gewoon het grote bit gebruiken als een tekenindicator met de Bits blijven die de absolute waarde van het nummer vertegenwoordigen.

  • Bij gebruik van de aanvulling van twee kan de variabele een groter bereik (met één) negatieve nummers vertegenwoordigen dan positieve nummers. Dit komt omdat nul is opgenomen in de ‘positieve’ nummers (omdat het tekenbit niet is ingesteld voor nul), maar niet de negatieve getallen. Dit betekent dat de absolute waarde van het kleinste negatieve getal niet kan worden weergegeven.

  • Bij gebruik van de aanvulling of ondertekende magnitude kunt u nul hebben weergegeven als een positief of negatief getal (dat een van een aantal redenen is dat deze representaties niet typisch worden gebruikt).


5, Autoriteit 3%

Alles behalve voor punt 2 is correct. Er zijn veel verschillende notaties voor ondertekende inten, sommige implementaties gebruiken de eerste, anderen gebruiken de laatste en nog anderen gebruiken iets heel anders. Dat hangt allemaal af van het platform waarmee je werkt.


6, Autoriteit 3%

Een ander verschil is wanneer u converteert tussen gehele getallen van verschillende maten.

Als u bijvoorbeeld een geheel getal uit een byte-stream extraheren (bijvoorbeeld 16 bits voor eenvoud), met niet-ondertekende waarden, kunt u doen:

i = ((int) b[j]) << 8 | b[j+1]

(moet waarschijnlijk de 2 ND byte, maar ik vermoed dat de compiler het juiste ding zal doen)

Met ondertekende waarden zou u zich zorgen moeten maken over tekenextensie en doen:

i = (((int) b[i]) & 0xFF) << 8 | ((int) b[i+1]) & 0xFF

7

Over het algemeen is het correct. Zonder iets meer te weten over waarom je op zoek bent naar de verschillen die ik niet kan bedenken aan andere verschillende differentoren tussen ondertekend en niet-ondertekend.


8

Over en hoger wat anderen hebben gezegd, in C, kunt u een niet-ondertekend geheel getal overlopen; Het gedrag wordt gedefinieerd als modulus rekenkunde. U kunt een ondertekend geheel getal overlopen en, in theorie (hoewel niet in de praktijk op de huidige mainstream-systemen), de overloop een fout kan veroorzaken (misschien vergelijkbaar met een verdeling door nul-fout).


9

  1. Ja, Unsigned Integer kan grote waarde opslaan.
  2. Nee, er zijn verschillende manieren om positieve en negatieve waarden te tonen.
  3. Ja, een geheel getal met teken kan zowel positieve als negatieve waarden bevatten.

Antwoord 10

(in antwoord op de tweede vraag) Door alleen een tekenbit te gebruiken (en niet het complement van 2), kun je eindigen met -0. Niet erg mooi.


Antwoord 11

Getekende gehele getallen in C vertegenwoordigen getallen. Als aen bvariabelen zijn van het type integer met teken, zal de standaard nooit vereisen dat een compiler de expressie a+=bopslaat in aiets anders dan de rekenkundige som van hun respectieve waarden. Om zeker te zijn, als de rekenkundige som niet in azou passen, zou de processor misschienhet daar niet kunnen plaatsen, maar de standaard zou niet vereisen dat de compiler afkapt of wikkel de waarde in, of doe iets anders als waarden die de limieten voor hun typen overschrijden. Houd er rekening mee dat hoewel de standaard dit niet vereist, C-implementaties rekenkundige overlopen met ondertekende waarden mogen opvangen.

Getallen zonder teken in C gedragen zich als abstracte algebraïsche ringen van gehele getallen die congruent zijn modulo een macht van twee, behalve in scenario’s met conversies naar of bewerkingen met grotere typen. Het converteren van een geheel getal van elkegrootte naar een 32-bits type zonder teken zal het lid opleveren dat overeenkomt met dingen die congruent zijn met dat geheel getal mod 4.294.967.296. De reden dat het aftrekken van 3 van 2 4.294.967.295 oplevert, is dat het toevoegen van iets congruent aan 3 aan iets dat congruent is aan 4.294.967.295 iets congruent aan 2 oplevert.

Abstracte algebraïsche ringen zijn vaak handig om te hebben; helaas gebruikt C ondertekendheid als de beslissende factor voor het al dan niet gedragen van een type als een ring. Erger nog, niet-ondertekende waarden worden behandeld als getallen in plaats van ringleden wanneer ze worden geconverteerd naar grotere typen, en niet-ondertekende waarden kleiner dan intworden geconverteerd naar getallen wanneer er een rekenkundige bewerking op wordt uitgevoerd. Als veen uint32_tis die gelijk is aan 4,294,967,294, dan moet v*=v;v=4. Helaas, als int64 bits is, is het niet te zeggen wat v*=v;zou kunnen doen.

Gezien de standaard zoals die is, zou ik willen voorstellen om niet-ondertekende typen te gebruiken in situaties waarin men het gedrag geassocieerd met algebraïsche ringen wil, en ondertekende typen wanneer men getallen wil vertegenwoordigen. Het is jammer dat C het onderscheid heeft gemaakt zoals het deed, maar ze zijn wat ze zijn.


Antwoord 12

Niet-ondertekende gehele getallen hebben veel meer kans om u in een bepaalde val te vangen dan getekende gehele getallen. De valkuil komt voort uit het feit dat terwijl 1 & 3 hierboven correct zijn, aan beide typen gehele getallen kan een waarde worden toegewezenbuiten de grenzen van wat het kan “houden” en het zal stil worden geconverteerd.

unsigned int ui = -1;
signed int si = -1;
if (ui < 0) {
    printf("unsigned < 0\n");
}
if (si < 0) {
    printf("signed < 0\n");
}
if (ui == si) {
    printf("%d == %d\n", ui, si);
    printf("%ud == %ud\n", ui, si);
}

Als je dit uitvoert, krijg je de volgende uitvoer, ook al zijn beide waarden toegewezen aan -1 en zijn ze anders gedeclareerd.

signed < 0
-1 == -1
4294967295d == 4294967295d

13

U moet niet-ondertekende gehele getallen gebruiken bij het programmeren op ingebouwde systemen. In loops, wanneer er geen behoefte is aan ondertekende gehele getallen, zal het gebruik van niet-ondertekende gehele getallen veilig opslaan die nodig is voor het ontwerpen van dergelijke systemen.

Other episodes