1. Avrunding av reelle tall

Som vi allerede har diskutert, når et reelt tall er tilordnet en intvariabel, rundes det alltid ned til nærmeste mindre heltall - brøkdelen blir ganske enkelt forkastet.

Men det er lett å forestille seg en situasjon der et brøktall må rundes av til nærmeste heltall i begge retninger eller til og med rundes opp. Hva gjør du i dette tilfellet?

For denne og for mange lignende situasjoner har Java klassen Math, som har metodene round(), ceil(), og floor().


Math.round()metode

Metoden Math.round()runder av et tall til nærmeste heltall:

long x = Math.round(real_number)

Men det er en annen nyanse her: denne metoden returnerer et longheltall (ikke et int). Fordi reelle tall kan være veldig store, bestemte Javas skapere å bruke Javas største tilgjengelige heltallstype: long.

Følgelig, hvis en programmerer ønsker å tilordne resultatet til en intvariabel, må hun eksplisitt indikere til kompilatoren at hun aksepterer mulig tap av data (i tilfelle at det resulterende tallet ikke passer inn i en inttype).

int x = (int) Math.round(real_number)

Eksempler:

Uttalelse Resultat
int x = (int) Math.round(4.1);
4
int x = (int) Math.round(4.5);
5
int x = (int) Math.round(4.9);
5

Math.ceil()metode

Metoden Math.ceil()runder et tall opp til et heltall. Her er eksempler:

Uttalelse Resultat
int x = (int) Math.ceil(4.1);
5
int x = (int) Math.ceil(4.5);
5
int x = (int) Math.ceil(4.9);
5

Math.floor()metode

Metoden Math.floor()runder et tall ned til et heltall. Her er eksempler:

Uttalelse Resultat
int x = (int) Math.floor(4.1);
4
int x = (int) Math.floor(4.5);
4
int x = (int) Math.floor(4.9);
4

Selvfølgelig, når du runder et tall ned til et heltall, er det lettere å bare bruke en type cast-operator:(int)

Uttalelse Resultat
int x = (int) 4.9
4

Hvis du synes det er vanskelig å huske disse navnene, vil en kort engelsk leksjon hjelpe:

  • Mathbetyr matematikk
  • Roundbetyr runde
  • Ceilingbetyr tak
  • Floorbetyr gulv

2. Hvordan flyttetallene er bygget opp

Typen doublekan lagre verdier i området fra til . Dette enorme spekteret av verdier (sammenlignet med typen) forklares av det faktum at typen (samt ) har en helt annen intern struktur enn heltallstyper. Internt koder typen verdien som to tall: det første kalles mantissen , og det andre kalles eksponenten .-1.7*10308+1.7*10308intdoublefloatdouble

La oss si at vi har tallet 123456789og lagrer det som en doublevariabel. Når vi gjør det, konverteres tallet til , og internt lagrer typen to tall - og . Signifikanden («signifikant del av tallet» eller mantissa) er uthevet i rødt, mens eksponenten er uthevet i blått.1.23456789*108double234567898

Denne tilnærmingen gjør det mulig å lagre både svært store og svært små. Men fordi tallets representasjon er begrenset til 8 byte (64 biter) og noen av bitene brukes til å lagre eksponenten ( så vel som tegnet på mantissen og tegnet til eksponenten), er de maksimale sifrene tilgjengelig for å representere mantissen er 15 .

Dette er en veldig forenklet beskrivelse av hvordan reelle tall er bygget opp.


3. Tap av presisjon ved arbeid med reelle tall

Når du arbeider med reelle tall, husk alltid at reelle tall ikke er eksakte . Det kan alltid være avrundingsfeil og konverteringsfeil ved konvertering fra desimal til binær. I tillegg er den vanligste feilkilden tap av presisjon når man adderer/subtraherer tall på radikalt forskjellige skalaer.

Dette siste faktum er litt oppsiktsvekkende for nybegynnere programmerere.

Hvis vi trekker fra , får vi .1/109109109

Å trekke fra tall på radikalt forskjellige skalaer Forklaring
 1000000000.000000000;
-         0.000000001;
 1000000000.000000000;
Det andre tallet er ekstremt lite , noe som vil føre til at dets signifikans (uthevet i grått) blir ignorert. De 15 signifikante sifrene er uthevet i oransje.

Hva kan vi si, programmering er ikke det samme som matematikk.


4. Fallgruve ved sammenligning av reelle tall

En annen fare ligger på lur for programmerere når de sammenligner reelle tall. Det oppstår når man jobber med reelle tall, fordi avrundingsfeil kan hope seg opp. Resultatet er at det er situasjoner der reelle tall forventes å være like, men det er de ikke. Eller omvendt: tallene forventes å være forskjellige, men de er like.

Eksempel:

Uttalelse Forklaring
double a = 1000000000.0;
double b = 0.000000001;
double c = a - b;
Verdien av variabelen a vil være 1000000000.0
Verdien av variabelen c vil være 1000000000.0
(tallet i b variabelen er for lite)

I eksemplet ovenfor, aog cbør ikke være like, men de er.

Eller la oss ta et annet eksempel:

Uttalelse Forklaring
double a = 1.00000000000000001;
double b = 1.00000000000000002;
Verdien av variabelen a vil være 1.0
Verdien av variabelen b vil være1.0

5. Et interessant faktum omstrictfp

Java har et spesielt nøkkelordstrictfp ( strict f loating point ), som ikke finnes i andre programmeringsspråk. Og vet du hvorfor du trenger det? Det forverrer nøyaktigheten av operasjoner med flyttall. Her er historien om hvordan det ble til:

Javas skapere:
Vi ønsker virkelig at Java skal være superpopulært og kjøre Java-programmer på så mange enheter som mulig. Så vi sørget for at spesifikasjonen for Java-maskinen sier at alle programmer må kjøre på samme måte på alle typer enheter!
Produsenter av Intel-prosessorer:
Hei alle sammen! Vi har forbedret prosessorene våre, og nå er alle reelle tall representert ved å bruke 10-byte i stedet for 8-byte inne i prosessorene våre. Flere byte betyr mer signifikante sifre. Hva betyr det? Det er riktig! Nå vil dine vitenskapelige beregninger være enda mer nøyaktige!
Forskere og alle som er involvert i ultranøyaktige beregninger:
Kul! Bra gjort. Gode ​​nyheter!
Javas skapere:
Nei-nei-nei, dere! Vi har allerede fortalt deg at alle Java-programmer må kjøre likt på alle enheter . Vi kommer til å tvangsdeaktivere muligheten til å bruke 10-byte reelle tall inne i Intel-prosessorer.
Nå er alt bra igjen! Ikke takk oss.
Forskere og alle som er involvert i ultranøyaktige beregninger:
Har du blitt helt gal? Få alt raskt tilbake som det var!
Javas skapere:
Gutter, dette er for ditt eget beste! Tenk deg: alle Java-programmer kjører på samme måte på alle enheter . Det er så kult!
Forskere og alle som er involvert i ultranøyaktige beregninger:
Nei. Det er ikke kult i det hele tatt. Sett alt raskt tilbake slik det var! Eller vet du hvor vi skal plassere Java?
Javas skapere:
Hmm. Hvorfor sa du ikke det med en gang? Selvfølgelig setter vi den tilbake.
Vi har gjenopprettet muligheten til å bruke alle funksjonene til de nyeste prosessorene.
Forresten... Vi har også lagt til nøkkelordet spesielt strictfptil språket. Hvis du skriver det før navnet på en funksjon, vil alle operasjonene som involverer reelle tall i den funksjonen være like dårlige på alle enheter !