1. Avrundning av reella tal
Som vi redan har diskuterat, när ett reellt tal tilldelas en int
variabel, avrundas det alltid nedåt till närmaste mindre heltal - bråkdelen kasseras helt enkelt.
Men det är lätt att föreställa sig en situation när ett bråktal måste avrundas till närmaste heltal i endera riktningen eller till och med avrundas uppåt. Vad gör du i det här fallet?
För detta och för många liknande situationer har Java Math
klassen, som har metoderna round()
, ceil()
, och .floor()
Math.round()
metod
Metoden Math.round()
avrundar ett tal till närmaste heltal:
long x = Math.round(real_number)
Men det finns en annan nyans här: den här metoden returnerar ett long
heltal (inte ett ) int
. Eftersom reella tal kan vara mycket stora, bestämde Javas skapare att använda Javas största tillgängliga heltalstyp: long
.
Följaktligen, om en programmerare vill tilldela resultatet till en int
variabel, måste hon uttryckligen ange för kompilatorn att hon accepterar eventuell förlust av data (i händelse av att det resulterande numret inte passar in i en int
typ).
int x = (int) Math.round(real_number)
Exempel:
Påstående | Resultat |
---|---|
|
|
|
|
|
|
Math.ceil()
metod
Metoden Math.ceil()
avrundar ett tal uppåt till ett heltal. Här är exempel:
Påstående | Resultat |
---|---|
|
|
|
|
|
|
Math.floor()
metod
Metoden Math.floor()
avrundar ett tal nedåt till ett heltal. Här är exempel:
Påstående | Resultat |
---|---|
|
|
|
|
|
|
Naturligtvis, när du avrundar ett tal nedåt till ett heltal, är det lättare att helt enkelt använda en typ cast-operator:(int)
Påstående | Resultat |
---|---|
|
|
Om du tycker att det är svårt att komma ihåg dessa namn hjälper en kort engelsklektion:
Math
betyder matematikRound
betyder rundCeiling
betyder takFloor
betyder golv
2. Hur flyttalstal är uppbyggda
Typen double
kan lagra värden i intervallet från till . Detta enorma utbud av värden (jämfört med typen) förklaras av att typen (liksom ) har en helt annan intern struktur än heltalstyper. Internt kodar typen sitt värde som två tal: det första kallas mantissa , och det andra kallas exponent .-1.7*10308
+1.7*10308
int
double
float
double
Låt oss säga att vi har numret 123456789
och lagrar det som en double
variabel. När vi gör det omvandlas numret till , och internt lagrar typen två nummer — och . Signifikanden ("signifikant del av talet" eller mantissa) är markerad i rött, medan exponenten är markerad i blått.1.23456789*108
double
23456789
8
Detta tillvägagångssätt gör det möjligt att lagra både mycket stora och mycket små. Men eftersom talets representation är begränsad till 8 byte (64 bitar) och en del av bitarna används för att lagra exponenten ( liksom mantisans tecken och exponentens tecken), är det maximala antalet tillgängliga siffror för att representera mantissan är 15 .
Detta är en mycket förenklad beskrivning av hur reella tal är uppbyggda.
3. Förlust av precision vid arbete med reella tal
När du arbetar med reella tal, tänk alltid på att reella siffror inte är exakta . Det kan alltid finnas avrundningsfel och konverteringsfel vid konvertering från decimal till binär. Dessutom är den vanligaste felkällan förlust av precision när man adderar/subtraherar tal på radikalt olika skalor.
Detta sista faktum är lite häpnadsväckande för nybörjare.
Om vi subtraherar från får vi .1/109
109
109
Subtrahera tal på radikalt olika skalor | Förklaring |
---|---|
|
Det andra numret är extremt litet , vilket gör att dess signifikans (markerad i grått) ignoreras. De 15 signifikanta siffrorna är markerade i orange. |
Vad kan vi säga, programmering är inte detsamma som matematik.
4. Fallgrop när man jämför reella tal
En annan fara ligger och väntar för programmerare när de jämför reella tal. Det uppstår när man arbetar med reella tal, eftersom avrundningsfel kan ackumuleras. Resultatet är att det finns situationer när reella tal förväntas vara lika, men de är det inte. Eller vice versa: siffrorna förväntas vara olika, men de är lika.
Exempel:
Påstående | Förklaring |
---|---|
|
Variabelns värde a kommer att vara 1000000000.0 Variabelns värde c kommer att vara 1000000000.0 (talet i b variabeln är för litet) |
I exemplet ovan, a
och c
bör inte vara lika, men de är.
Eller låt oss ta ett annat exempel:
Påstående | Förklaring |
---|---|
|
Variabelns värde a kommer att vara 1.0 Variabelns värde b kommer att vara1.0 |
5. Ett intressant faktum omstrictfp
Java har ett speciellt strictfp
nyckelord ( strict f loating point ) , som inte finns i andra programmeringsspråk. Och vet du varför du behöver det? Det försämrar noggrannheten i operationer med flyttal. Här är historien om hur det blev:
GO TO FULL VERSION