1. Afrunding af reelle tal

Som vi allerede har diskuteret, når et reelt tal tildeles en intvariabel, rundes det altid ned til det nærmeste mindre heltal - brøkdelen kasseres simpelthen.

Men det er let at forestille sig en situation, hvor et brøktal skal afrundes til det nærmeste heltal i begge retninger eller endda rundes op. Hvad gør du i dette tilfælde?

Til denne og til mange lignende situationer har Java klassen Math, som har metoderne round(), ceil(), og floor().


Math.round()metode

Metoden Math.round()afrunder et tal til nærmeste heltal:

long x = Math.round(real_number)

Men der er en anden nuance her: denne metode returnerer et longheltal (ikke et int). Fordi reelle tal kan være meget store, besluttede Javas skabere at bruge Javas største tilgængelige heltalstype: long.

I overensstemmelse hermed, hvis en programmør ønsker at tildele resultatet til en intvariabel, skal hun eksplicit indikere over for compileren, at hun accepterer det mulige tab af data (i tilfælde af at det resulterende tal ikke passer ind i en inttype).

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

Eksempler:

Udmelding 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 tal op til et heltal. Her er eksempler:

Udmelding 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 tal ned til et heltal. Her er eksempler:

Udmelding 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

Når du runder et tal ned til et heltal, er det selvfølgelig nemmere blot at bruge en type cast-operator:(int)

Udmelding Resultat
int x = (int) 4.9
4

Hvis du har svært ved at huske disse navne, vil en kort engelsk lektion hjælpe:

  • Mathbetyder matematik
  • Roundbetyder rund
  • Ceilingbetyder loft
  • Floorbetyder gulv

2. Hvordan floating-point tal er opbygget

Typen doublekan gemme værdier i området fra til . Denne enorme række af værdier (sammenlignet med typen) forklares ved, at typen (såvel som ) har en helt anden intern struktur end heltalstyper. Internt koder typen sin værdi som to tal: det første kaldes mantissen , og det andet kaldes eksponenten .-1.7*10308+1.7*10308intdoublefloatdouble

Lad os sige, at vi har tallet 123456789og gemmer det som en doublevariabel. Når vi gør det, konverteres tallet til , og internt gemmer typen to numre - og . Signifikanden ("signifikant del af tallet" eller mantisse) er fremhævet med rødt, mens eksponenten er fremhævet med blåt.1.23456789*108double234567898

Denne tilgang gør det muligt at lagre både meget store antal og meget små. Men fordi tallets repræsentation er begrænset til 8 bytes (64 bit), og nogle af bitsene bruges til at gemme eksponenten ( såvel som mantissens fortegn og eksponentens fortegn), er de maksimale cifre til rådighed til at repræsentere mantissen er 15 .

Dette er en meget forenklet beskrivelse af, hvordan reelle tal er opbygget.


3. Tab af præcision ved arbejde med reelle tal

Når du arbejder med reelle tal, skal du altid huske på, at reelle tal ikke er nøjagtige . Der kan altid være afrundingsfejl og konverteringsfejl ved konvertering fra decimal til binær. Derudover er den mest almindelige fejlkilde tab af præcision ved addering/fradrag af tal på radikalt forskellige skalaer.

Denne sidste kendsgerning er lidt åndssvag for nybegyndere.

Hvis vi trækker fra , får vi .1/109109109

At trække tal fra på radikalt forskellige skalaer Forklaring
 1000000000.000000000;
-         0.000000001;
 1000000000.000000000;
Det andet tal er ekstremt lille , hvilket vil medføre, at dets signifikans (fremhævet i gråt) ignoreres. De 15 signifikante cifre er fremhævet med orange.

Hvad kan vi sige, programmering er ikke det samme som matematik.


4. Faldgrube ved sammenligning af reelle tal

En anden fare ligger på lur for programmører, når de sammenligner reelle tal. Det opstår, når man arbejder med reelle tal, fordi der kan akkumuleres afrundingsfejl. Resultatet er, at der er situationer, hvor reelle tal forventes at være lige store, men det er de ikke. Eller omvendt: tallene forventes at være forskellige, men de er lige store.

Eksempel:

Udmelding Forklaring
double a = 1000000000.0;
double b = 0.000000001;
double c = a - b;
Værdien af ​​variablen a vil være 1000000000.0
Værdien af ​​variablen c vil være 1000000000.0
(tallet i b variablen er for lille)

I ovenstående eksempel, aog cbør ikke være ens, men de er.

Eller lad os tage et andet eksempel:

Udmelding Forklaring
double a = 1.00000000000000001;
double b = 1.00000000000000002;
Værdien af ​​variablen a vil være 1.0
Værdien af ​​variablen b vil være1.0

5. En interessant kendsgerning vedrstrictfp

Java har et særligt strictfpnøgleord ( strict f loating point ), som ikke findes i andre programmeringssprog. Og ved du hvorfor du har brug for det? Det forværrer nøjagtigheden af ​​operationer med flydende kommatal. Her er historien om, hvordan det blev til:

Javas skabere:
Vi ønsker virkelig at Java skal være super populært og køre Java-programmer på så mange enheder som muligt. Så vi sørgede for, at specifikationen for Java-maskinen siger, at alle programmer skal køre ens på alle typer enheder!
Producenter af Intel-processorer:
Hey alle sammen! Vi har forbedret vores processorer, og nu er alle reelle tal repræsenteret ved hjælp af 10-bytes i stedet for 8-bytes inde i vores processorer. Flere bytes betyder flere signifikante cifre. Hvad betyder det? Det er rigtigt! Nu bliver dine videnskabelige beregninger endnu mere nøjagtige!
Forskere og alle involverede i ultrapræcise beregninger:
Fedt nok! Godt klaret. Fremragende nyheder!
Javas skabere:
Nej-nej-nej, jer! Vi har allerede fortalt dig, at alle Java-programmer skal køre ens på alle enheder . Vi vil tvangsdeaktivere muligheden for at bruge 10-byte reelle tal inde i Intel-processorer.
Nu er alt godt igen! Tak os ikke.
Forskere og alle involverede i ultrapræcise beregninger:
Er du blevet helt sindssyg? Få hurtigt alt tilbage, som det var!
Javas skabere:
Gutter, det er for jeres eget bedste! Bare forestil dig: alle Java-programmer kører på samme måde på alle enheder . Det er så sejt!
Forskere og alle involverede i ultrapræcise beregninger:
Nej. Det er slet ikke fedt. Sæt hurtigt alt tilbage, som det var! Eller ved du, hvor vi placerer din Java?
Javas skabere:
Hmm. Hvorfor sagde du det ikke med det samme? Selvfølgelig lægger vi det tilbage.
Vi har genoprettet din mulighed for at bruge alle funktionerne i de nyeste processorer.
Forresten... Vi har også specielt tilføjet nøgleordet strictfptil sproget. Hvis du skriver det før navnet på en funktion, vil alle operationer, der involverer reelle tal inde i den funktion, være lige dårlige på alle enheder !