Fra en Java- og C # -baggrund har jeg lært at bruge int
(32 bits), når jeg har brug for et helt tal, og double
(64 bits), når der behandles brøkværdier. De fleste metoder fra deres respektive rammer (JVM og .NET) forventer normalt disse to typer.
Mit spørgsmål er, hvorfor bruger vi ikke både long
og double
til konsistens? Jeg ved, at det ikke er nødvendigt at have 64 bit præcision i heltal, men igen har vi normalt ikke brug for 64 bit præcision i flydende tal, eller gør vi?
Hvad er ræsonnementet bag dette, hvis nogen?
Kommentarer
A nswer
Område vs. præcision
Én ting er, at jeg vil bestride ideen om, at det mest almindelige flydende nummer bruger en 64-bit DPFP-repræsentation (dobbelt-præcision flydende punkt).
I det mindste i præstationskritisk real- tidsfelter som spil, SPFP (single-precision floating-point) er stadig langt mere almindeligt, da tilnærmelse og hastighed der foretrækkes frem for den største nøjagtighed.
Endnu måske en måde at se på dette er, at en 32 -bit int
repræsenterer et interval på 2^32
heltal (~ 4,3 milliarder). Den mest almindelige anvendelse af heltal vil sandsynligvis være som indekser til elementer, og at “et ret sundt udvalg af elementer, som det ville være vanskeligt at overskride uden at overskride den tilgængelige hukommelse med nutidens hardware *.
* Bemærk, at der kan opstå hukommelsesfejl, når du tildeler / får adgang til en enkelt sammenhængende 4 gigabyte blok, selv med 30 gigabyte gratis, f.eks. på grund af sammenhængen kravene til denne blok.
Et 32-bit heltal er ikke altid mere effektivt på instruktionsniveauet, men det har tendens til generelt at være mere effektiv, når den samles i en matrix, f.eks. da den kræver halvdelen af hukommelsen (flere indekser, der kan passe ind i en enkelt side / cache-linje, f.eks.).
Bemærk også, at som Lightness Races in Orbit
påpeger, det er ikke nødvendigvis engang sandt fra et bredt perspektiv, at 32-bit heltal er mere almindeligt anvendte. Jeg har mit snævre perspektiv fra et felt, hvor 32-bit ints
ofte aggregeres af hundreder af tusinder til millioner som indekser i en anden struktur – der kan halveringen i størrelse hjælpe en parti.
Nu kan 64-bit DPFP muligvis bruges meget mere end 64-bit heltal i nogle sammenhænge. Der tilføjer de ekstra bits præcision snarere end rækkevidde . Mange applikationer kan kræve præcision eller i det mindste have en meget lettere tidsprogrammering med ekstra præcision til rådighed. Så det er sandsynligvis, hvorfor 64-bit DPFPer måske er mere almindelige end 64-bit heltal i nogle områder, og hvorfor int
stadig kan være 32-bit i mange scenarier, selv på 64-bit platforme.
Kommentarer
- Jeg ‘ d bestride ideen at den mest almindelige integrerede datatype også er 32 bit bred, i det mindste i programmer, der er skrevet i dag på råvarehardware. 64-bit-platforme er så udbredte nu.
- @I Ke: Sagen er, at jeg formoder, at meget software bare bruger
int
oglong
uden virkelig at være opmærksom på, hvad området er … og sådan software bruger jeg, overvejende 64-bit heltal i begge tilfælde i dag. - Hmm jeg står korrigeret; tilsyneladende er
int
generelt stadig 32-bit stort set for at undgå at introducere bugs i netop den slags kode. Ok ja, du ‘ har stadigsize_t
oglong
. - @LightnessRacesinOrbit Ah, jeg ser, jeg ‘ er ekstremt forudindtaget, da jeg ofte arbejder i kodebaser, der samler heltal i en vis datastruktur med bekymring over den samlede hukommelsesstørrelse. Jeg forsøgte at gøre mit svar så neutralt som muligt.
- @I ke: Personligt gør jeg også alle mine typer eksplicit størrelse.Men du og jeg er uden tvivl unormale. 🙂
Svar
Nå, int og dobbelt er en Java-ting. For eksempel i Objective-C og Swift bruger du NSInteger eller Int, som er 32 bit på en 32 bit maskine og 64 bit på en 64 bit maskine. Stor nok til at tælle et hvilket som helst antal ting, der måtte være i hukommelsen. Hvad der bestemt er nyttigt er at bruge den samme type næsten overalt, medmindre du i en bestemt situation har brug for noget andet.
Java forsøger at have kode, der kører den samme på enhver implementering, så de mener, at du skal bruge den samme type uafhængigt af den maskine, du bruger, og at typen skal have det samme antal bits uafhængigt af maskinen. Objective-C og Swift (og C, C ++ også) har et andet synspunkt.
Heltal bruges oftest til at tælle ting, og normalt har du ikke så mange ting at tælle. Flydende aritmetik har brug for præcision, og 32 bit flydende punkt giver dig ofte ikke tilstrækkelig præcision. Brug af 64 bit dobbelt overalt giver dig en kæmpechance til altid at have tilstrækkelig præcision uden at være specialist i flydende aritmetik. float gør ikke det.
Men hvilken konsistens ville bruge lang og dobbelt give dig? Heltal og flydende punktum er ikke den samme ting. Der er ikke behov for at have ensartet bitstørrelse. Jeg bruger 2D-punkter og rektangler meget. Så for konsistens, skal de også være 64 bit? Point med 32 bit pr. komponent, og rektangler med 16? Selvfølgelig ikke. Ingen konsistens nødvendig.
Kommentarer
- Dette er et meget flot svar, der forklarer JVM-siden af det at holde størrelsen på hver type den samme uanset platformen.
Svar
kort, int, enkelt og dobbelt har samme størrelse i java, da de er i de mest almindelige C-kompilatorer til 32-bit og 64-bit platforme og C som java betragter klart int som den vigtigste heltalstype og dobbelt som den vigtigste flydende punkttype. Jeg synes det er rimeligt at sige, at Java arvede denne konvention fra almindelige C-kompilatorer på det tidspunkt.
Heltal er normalt brugt til c plyndring eller indeksering af ting. Det er ret sjældent (dog ikke uhørt) at skulle tælle eller indeksere mere end 2 milliarder af noget. Faktisk før C99 var du nødt til at bruge leverandørspecifikke typer, hvis du ville have et 64-bit heltal.
Flydende numre bruges normalt som en tilnærmelse af de reelle tal. Enkel præcision er god nok meget af tiden, men det er ikke svært at finde problemer, hvor det forårsager en uacceptabel mængde afrundingsfejl. Jeg forventer, at efterspørgsel fra videnskabelig computing er det, der kørte dobbelt præcision med flydende punktstøtte til at være allestedsnærværende længe før 64-bit heltal understøttelse var.
Hvad jeg synes er nysgerrig, er at C synes at tilskynde til brug af dobbelt, mens fortran synes at tilskynde til brug af en enkelt præcision.
BigDecimal
til flydende tal, siden afrunding og at sammenligne FP-værdier er så problematisk.