Jag kommer från en Java- och C # -bakgrund och har lärt mig att använda int
(32 bitar) när jag behöver ett heltal och double
(64 bitar) när det gäller bråkvärden. De flesta metoder från deras respektive ramverk (JVM och .NET) förväntar sig vanligtvis dessa två typer.
Min fråga är, varför använder vi inte både long
och double
för konsistens? Jag vet att det inte behövs 64 bitar av precision i heltal, men då behöver vi vanligtvis inte 64 bitar av precision i flytande siffror, eller gör vi det?
Vad är resonemanget bakom detta, om något?
Kommentarer
A nswer
Område kontra precision
En sak är att jag skulle bestrida tanken att det vanligaste flytpunkten använder en 64-bitars DPFP (dubbel precision-flytpunkt) -representation.
Åtminstone i prestandakritisk verklig tidsfält som spel, SPFP (floating-point med en enda precision) är fortfarande mycket vanligare, eftersom approximation och hastighet där är att föredra framför största noggrannhet.
Ändå kanske ett sätt att titta på detta är att en 32 -bit int
representerar ett intervall av 2^32
heltal (~ 4,3 miljarder). Den vanligaste användningen av heltal kommer antagligen att vara som index för element, och att ”ett ganska hälsosamt utbud av element som skulle vara svåra att överstiga utan att överskrida det minne som finns tillgängligt med dagens hårdvara *.
* Observera att minnesfel kan uppstå vid tilldelning / åtkomst av ett enda, sammanhängande 4 gigabyte block även med 30 gigabyte ledigt, t.ex. på grund av sammanhängningen kraven i det blocket.
Ett 32-bitars heltal är inte alltid effektivare på instruktionsnivån, men det är tenderar i allmänhet att vara effektivare när de samlas i en matris, t.ex. eftersom det kräver hälften av minnet (fler index som kan passa in i en enda sida / cache-rad, t.ex.).
Observera också att som Lightness Races in Orbit
påpekar, det är inte nödvändigtvis ens sant ur ett brett perspektiv att 32-bitars heltal används oftare. Jag har mitt snäva perspektiv från ett fält där 32-bitars ints
ofta sammanställs av hundratusentals till miljoner som index i en annan struktur – där kan halveringen i storlek hjälpa mycket.
Nu kan 64-bitars DPFP användas mycket mer än 64-bitars heltal i vissa sammanhang. Där lägger de extra bitarna till precision snarare än intervall . Många applikationer kan kräva precision, eller åtminstone ha en mycket enklare programmering med extra precision tillgänglig. Så det är förmodligen varför 64-bitars DPFP kanske är vanligare än 64-bitars heltal i vissa områden, och varför int
fortfarande kan vara 32 bitar i många scenarier även på 64-bitars plattformar.
Kommentarer
- Jag ’ d bestrider idén att den vanligaste integrala datatypen också är 32 bitar bred, åtminstone i program som skrivs idag på råvaruhårdvara. 64-bitars plattformar är så utbredda nu.
- @I Ke: Det är jag som misstänker att mycket programvara bara använder
int
ochlong
utan att verkligen bry sig om vad intervallet är … och sådan programvara tror jag huvudsakligen använder 64-bitars heltal i båda fallen nuförtiden. - Hmm jag står rättad; tydligen är
int
i allmänhet fortfarande 32-bitars , till stor del för att undvika att införa fel i just den typen av kod. Okej, du ’ har fortfarandesize_t
ochlong
. - @LightnessRacesinOrbit Ah, jag förstår, jag ’ är extremt partisk eftersom jag ofta arbetar i kodbaser som sammanställer heltal i någon datastruktur med en oro över den totala minnesstorleken. Jag försökte göra mitt svar så neutralt som möjligt.
- @I ke: Personligen gör jag också alla mina typer uttryckligen storlek.Men du och jag är utan tvekan onormala. 🙂
Svar
Tja, int och dubbel är en Java-sak. Till exempel, i Objective-C och Swift skulle du använda NSInteger eller Int, som är 32 bitar på en 32-bitars maskin och 64 bitar på en 64-bitars maskin. Stor nog att räkna valfritt antal objekt som kan finnas i minnet. Det som är definitivt användbart är att använda samma typ nästan överallt, såvida du inte behöver något annat i en viss situation.
Java försöker ha kod som kör samma på alla implementeringar, så de tycker att du ska använda samma typ oberoende av den maskin du använder, och att typen ska ha samma antal bitar oberoende av maskinen. Objective-C och Swift (och C, C ++ också) har en annan synvinkel.
Heltal används mest för att räkna saker, och vanligtvis har du inte så många saker att räkna. Flytpunktsberäkning behöver precision och 32-bitars flytpunkt ger dig inte tillräckligt med precision. Att använda 64-bitars dubbla överallt ger dig en stridschans att alltid ha tillräckligt med precision, utan att vara specialist på flytpunktsräkning. float gör inte det.
Men vilken konsistens skulle du använda långa och dubbla? Heltal och flytande siffror är inte samma sak. Det finns inget behov av att de har konsekvent bitstorlek. Jag använder 2D-punkter och rektanglar mycket. För konsistens, borde de också vara 64 bitar? Poäng med 32 bitar per komponent och rektanglar med 16? Naturligtvis inte. Ingen konsistens behövs.
Kommentarer
- Detta är ett mycket trevligt svar som förklarar JVM-sidan av det att hålla storleken på varje typ oavsett plattform.
Svar
korta, int, enkla och dubbla har samma storlek i java som de är i de vanligaste C-kompilatorerna för 32-bitars och 64-bitars plattformar och C som java anser tydligt att int är den huvudsakliga heltalstypen och dubbel är den huvudsakliga flytpunktstypen. Jag tycker att det är rimligt att säga att Java ärvde denna konvention från vanliga C-kompilatorer vid den tiden.
Heltal är vanligtvis används för c ounting eller indexering saker. Det är ganska sällsynt (men inte ovanligt) att behöva räkna eller indexera mer än 2 miljarder av något. Innan C99 var du tvungen att använda leverantörsspecifika typer om du ville ha ett 64-bitars heltal.
Flytpunktsnummer används vanligtvis som en approximation av de verkliga siffrorna. Enstaka precision är tillräckligt bra mycket av tiden men det är inte svårt att hitta problem där det orsakar en oacceptabel mängd avrundningsfel. Jag förväntar mig att efterfrågan från vetenskaplig databehandling är det som körde stöd för dubbla precisionsflytpunktsytor långt före 64-bit heltalsstöd var.
Vad jag tycker är nyfiken är att C verkar uppmuntra till användning av dubbel medan fortran verkar uppmuntra till användning av enstaka precision.
BigDecimal
för flytande siffror, eftersom avrundning att jämföra FP-värden är så problematiskt.