Negative Zero

Originally published by Howdy Pierce on November 17th 2017 6,483 reads

Howdy Pierce Hacker ' s middags profielfoto

@howdypierceHowdy Pierce

Voorzitter en Oprichter

facebook sociale pictogramTwitter sociale pictogram

Mijn vrouw brengt tot het volgende verhaal elke keer als ze wil om zijn punt te maken dat ik ben formeel: Als een van mijn dochters was in het tweede leerjaar, haar wiskunde leraar zei tegen de klas dat een getal gedeeld door nul is. Ik stootte een hartstochtelijke e-mail af naar de leraar, volhoudend dat het resultaat ongedefinieerd moest zijn. Vermoedelijk is dit het bewijs dat ik soms moeilijk ben om in de buurt te zijn.

blijkt dat de grap misschien op mij is-hoewel het nog steeds moeilijk is om het antwoord van de leraar van de tweede klas te ondersteunen. Ik heb onlangs een hoop dingen geleerd die ik niet wist over floating point math:

  • Er is een waarde voor negatieve nul, los van regulier (positief?) nul. Deze twee nullen zijn gedefinieerd om gelijk te zijn aan elkaar en toch zijn ze verschillende waarden.
  • x ÷ 0.0, voor x ≠ ±0.0, is geen fout. In plaats daarvan is het resultaat ofwel positieve oneindigheid of negatieve oneindigheid, volgens de gebruikelijke tekenconventie.
  • het geval van ±0.0 ÷ ±0.0 is een fout (specifiek is het “geen getal” of NaN).
  • -0.0 + -0.0 = -0.0, -0.0 + 0.0 = 0.0, en -0,0 × 0,0 = -0,0

deze regels komen voort uit de IEEE 754 “Standard for Floating-Point Arithmetic”, die floating-point representations over platforms gestandaardiseerde. De meest recente versie van de standaard werd voltooid in 2008, maar de originele versie werd uitgegeven in 1985, dus dit gedrag is niet nieuw. De bovenstaande regels zijn waar in zowel C (gcc) en Swift op mijn Mac, en ook waar in Swift op een iPhone. Python op de Mac ondersteunt negatieve nul voor drijft, maar gooit een uitzondering wanneer u probeert te delen door nul van een teken.

Er zijn een paar verrassende corollaries aan deze regels:

  • omdat 0.0 en -0.0 als gelijk moeten worden vergeleken, moet de test (x < 0.0) retourneert niet waar voor elk negatief getal — het faalt voor negatieve nul. Om het teken van een nulwaarde te bepalen, moet u daarom de ingebouwde tekenfunctie van het platform gebruiken, bijvoorbeeld Double.meld je aan Swift. Of ik denk dat je de ruwe representatie van de dubbel kunt bit-manipuleren, wat eigenlijk het antwoord is van een C programmeur.
  • als a = b ÷ c, volgt dit niet noodzakelijkerwijs dat b = a × c, omdat dit ook faalt voor het geval waarin c nul is van een van beide tekens.

Ik ben geen getaltheoreticus, maar ik vind de bovenstaande concepten verrassend.

Eén direct probleem: Oneindigheid is geen getal, zoals nul of 3,25 of π. In plaats daarvan is oneindigheid een concept. Het is waar dat de rationale getallen aftelbaar oneindig zijn — maar oneindigheid is geen lid van de verzameling rationale getallen.

verder is deling door nul vanuit een getaltheoretisch perspectief onzinnig. Je kunt begrijpen waarom als je precies weet wat verdeeldheid betekent. Technisch gezien is “deling” “vermenigvuldiging met de inverse van een getal”, waarbij de inverse voldoet aan: a × A^-1 = 1. Nul is het enige getal in de verzameling van reële getallen dat simpelweg geen multiplicatieve inverse heeft. En omdat deze inverse niet bestaat, kunnen we er niet mee vermenigvuldigen.

maar zeker de mensen die floating point getallen ontwierpen wisten dit allemaal. Ik vroeg me af waarom het beschreven gedrag in de IEEE-standaard werd geschreven.

om te beginnen, laten we eens kijken naar het probleem dat floating-point math probeert aan te pakken. De reële getallen zijn ontelbaar oneindig, en toch willen we deze hele verzameling vertegenwoordigen binnen de grenzen van het eindige computergeheugen. Met een 64-bit double zijn er 2^64 mogelijke symbolen, en de ontwerpers van de IEEE-standaard probeerden deze symbolen in kaart te brengen op de set van reële getallen op een manier die zowel nuttig was voor real-world toepassingen als ook economisch haalbaar was gezien de beperkingen van het begin van de jaren 80 silicium. Gezien de basisvereisten zouden duidelijk benaderingen worden gebruikt.de redenering voor negatieve nul lijkt te dateren uit 1987 door William Kahan, een Berkeley professor die wordt beschouwd als de “vader van floating point” en die later de Turing Award won voor zijn werk in het opstellen van IEEE 754. Het blijkt dat het bestaan van negatieve nul nauw verbonden is met het vermogen om te delen door nul.

laten we beginnen met het bespreken van de gebruikelijke reden dat delen door nul niet is toegestaan. Een naïeve benadering van deling door nul is de waarneming dat:

met andere woorden, als x kleiner wordt, wordt het resultaat van 1/x groter. Maar dit is alleen waar als x 0 benadert vanaf de positieve kant (daarom is er dat kleine plusteken hierboven). Het uitvoeren van dezelfde gedachte experiment van de negatieve kant:

hierdoor is de algemene limiet van 1/x als x nadert 0 niet gedefinieerd, omdat er een discontinuïteit is (wat Kahan een slit noemt) in de functie 1/x.

met de invoering van een ondertekende nul konden Kahan en de IEEE-Commissie de moeilijkheid omzeilen. Intuïtief wordt het teken van een nul genomen om aan te geven vanuit welke richting de grens wordt benaderd. Zoals Kahan zegt in zijn artikel uit 1987:

in plaats van te denken aan +0 en -0 als verschillende numerieke waarden, denk aan hun teken bit als een hulpvariabele die een beetje informatie (of verkeerde informatie) over een numerieke variabele die 0 als waarde neemt overbrengt. Meestal is deze informatie irrelevant; de waarde van 3+x is niet anders voor x := +0 dan voor x := -0…. Echter, een paar buitengewone rekenkundige bewerkingen worden beïnvloed door nulteken; bijvoorbeeld 1/ (+0) = +∞ maar 1/ (-0) = –∞.

Ik heb vrede gesloten met het concept door het aannemen van een rationalisatie voorgesteld door mijn partner Mike Perkins: de 2^64 beschikbare symbolen zijn duidelijk ontoereikend om het geheel van de verzameling van reële getallen weer te geven. De IEEE-ontwerpers zetten een paar van die symbolen opzij voor speciale betekenissen. In deze zin betekent ∞ niet echt “oneindigheid” — in plaats daarvan betekent het “een reëel getal dat groter is dan we anders kunnen vertegenwoordigen in onze floating-point symboolset.”En daarom betekent +0 niet echt “nul”, maar eerder ” een reëel getal dat groter is dan waar 0, maar kleiner dan elk positief getal dat we kunnen vertegenwoordigen.”

overigens, tijdens het onderzoeken van dit probleem, ontdekte ik dat zelfs Kahan niet van het idee van negatieve nul houdt:

ondertekende nul — nou, de ondertekende nul was een lastpost die we konden elimineren als we de Projectieve modus gebruikten. Als er slechts één oneindigheid en één nul was, kon je het prima doen; dan gaf je niets om het teken van nul en je gaf niets om het teken van oneindigheid. Maar als, aan de andere kant, je aandrong op wat ik zou hebben beschouwd als de mindere keuze van twee oneindigheden, dan ga je eindigen met twee getekende nullen. Er was echt geen manier om dat te omzeilen en je zat ermee opgescheept.”(Uit een interview van Kahan uitgevoerd in 2005.)

Ik weet niet zeker of het schrijven van een blogpost tien jaar later een slechte tweede klas leraar goed maakt. Van haar kant rolde mijn dochter, nu op de middelbare school, haar ogen toen ik begon te praten over Divisie door nul tijdens het diner. Misschien is dat ‘moeilijk om in de buurt te zijn’ erfelijk.

Kahan, W., “Branch Cuts for Complex Elementary Functions, or Much Ado About Nothing ‘S Sign Bit”, The State of the Art in Numerical Analysis, (Eds. Iserles and Powell), Clarendon Press, Oxford, 1987, hier beschikbaar.

Tags

Join Hacker Noon

Create your free account om uw aangepaste leeservaring te ontgrendelen.

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *