Innehållsförteckning:
Video: String Theory Explained – What is The True Nature of Reality? 2024
Tror det eller inte, datorer - även de mest kraftfulla - har vissa begränsningar när det gäller att utföra matematiska beräkningar. Dessa begränsningar är vanligtvis obetydliga, men ibland slår de sig och biter på dig. Här är de saker du behöver se upp för när du gör matte i Java.
Helhetsflöde
Det grundläggande problemet med heltalstyper är att de har en fast storlek. Som ett resultat är det en gräns för storleken på de siffror som kan lagras i variabler av typen
kort
,
int
eller
lång
. Även om
långa
-variablerna kan innehålla siffror som är stora, kommer du förr eller senare över ett nummer som är för stort för att passa in i en
lång
-variabel.
Okej, betrakta detta (antagligen konstruerat) exempel:
int a = 1000000000;
System. ut. println (a);
a + = 1000000000;
System. ut. println (a);
a + = 1000000000;
System. ut. println (a);
a + = 1000000000;
System. ut. println (a);
Här förväntar du dig att värdet på
a
blir större efter varje tillägg. Men här är resultatet som visas:
1000000000
2000000000
-1294967296
-294967296
Den första tillägget verkar fungera, men efter det blir numret negativt! Det beror på att värdet har nått storleken på
int
datatypen. Tyvärr berättar Java inte om att det här felet har hänt. Den klämmer helt enkelt in
int
-variabeln så mycket som möjligt, kassera vad som helst som inte passar och hoppas att du inte märker. På grund av hur
int
lagrar negativa värden blir stora positiva värden plötsligt stora negativa värden.
Historien är att om du arbetar med stora heltal bör du använda
lång
i stället för
int
, eftersom
lång
kan lagra mycket större siffror än
int
. Om dina program hanterar siffror som är tillräckligt stora för att vara ett problem för
lång
, bör du överväga att använda flytande typer i stället. Flyttpunktstyper kan hantera ännu större värden än
lång
, och de meddelar dig när du överstiger deras kapacitet.
Flytande suddighet
Flytande siffror har egna problem. För att börja med lagras flytande punkttal med hjälp av det binära nummersystemet (bas 2), men människor arbetar med siffror i decimalsystemet (bas 10). Tyvärr är det ibland omöjligt att konvertera siffror mellan dessa två system. Det beror på att i några talbaser kan vissa fraktioner inte representeras exakt.
Ett exempel: Bas 10 har ingen möjlighet att exakt representera fraktionen 1/3. Du kan approximera den som 0. 3333333, men så småningom når du gränsen för hur många siffror du kan lagra, så du måste sluta. I bas 2 händer det att en av de fraktioner som du inte kan korrekt representera är decimalvärdet 1/10. Med andra ord kan en
float
eller
dubbel
variabel inte exakt representera
0. 1
.
Försök att köra den här koden:
float x = 0. 1f;
NumberFormat nf = NumberFormat. getNumberInstance ();
nf. setMinimumFractionDigits (10);
System. ut. println (nf. format (x));
Resultatet är följande:
0. 1000000015
Även om
0. 1000000015
är close till
0. 1
, det är inte exakt.
I de flesta fall är Java's flytande punktmatematik tillräckligt nära att inte betyda. Felmarginalen är extremt liten. Om du använder Java för att mäta storleken på ditt hus, skulle du behöva ett elektronmikroskop för att märka felet. Om du skriver applikationer som handlar om finansiella transaktioner kan normal avrundning ibland förstora felen för att göra dem signifikanta. Du kan ta ut en öre för mycket eller för liten moms. Och i extrema fall kan fakturorna faktiskt ha uppenbara tilläggsfel.
Naturligtvis lagras även heltalstyper i binär. Men heltal är inte föremål för samma fel som flytande typer är - eftersom heltal inte representerar fraktioner alls - så du behöver inte oroa dig för denna typ av fel för
heltal
typer.
Division noll
Enligt matematikens grundläggande regler kan du inte dela ett tal med noll. Anledningen är enkel: Division är invers av multiplikation - vilket betyder att om
a * b = c
är det också sant att
a = c / b
. Om du skulle tillåta
b
att vara noll, skulle division vara meningslös, eftersom alla antal gånger noll är noll. Därför måste både
a
och
c
också vara noll. Kort sagt, matematiker löst detta dilemma århundraden sedan genom att säga att division med noll helt enkelt inte är tillåtet.
Så vad händer om du gör försök att dela ett tal med noll i ett Java-program? Svaret beror på huruvida du delar upp heltal eller flytande siffror. Om du delar upp heltal, stämmer det uttalande som försöker uppdelningen med noll chocker upp vad som kallas ett undantag, vilket är ett orättvist sätt att krascha programmet.
Det finns ett sätt att avlyssna detta undantag så att ditt program kan fortsätta som du inte hittar här. Under tiden kommer ett program du skriver som försöker ett heltal med nollkrascher.
Om du försöker dela en flytpunktstyp med noll, är resultatet inte så brått. Istället tilldelas Java ett resultat av flytande punkt ett av de specialvärden som anges i tabellen nedan. Följande stycken förklarar hur dessa specialvärden bestäms:
- Om du delar ett tal med noll, och tecknet på båda talen är densamma, är resultatet en positiv oändlighet.
0. 0
dividerat med0. 0
är positiv oändlighet, liksom-34. 0
dividerat med-0. 0
. - Om du delar ett nummer med noll, och tecknen på siffrorna är olika, är resultatet negativt oändligt.
-40. 0
dividerat med0. 0
är negativ oändlighet, liksom34. 0
dividerat med0. 0
. - Om du delar noll med noll, är resultatet inte ett tal (NaN), oavsett tecken.
Konstant | Betydelse |
POSITIVE_INFINITY
|
Positiv oändlighet |
NEGATIVE_INFINITY
|
Negativ oändlighet |
NaN
|
Ej ett tal |
Flytande nollor kan vara positiva eller negativa. Java anser att positiva och negativa nollor är lika numeriska.
Om du försöker skriva ut ett flytande punktvärde som har ett av dessa specialvärden konverterar Java värdet till en lämplig sträng. Antag att du utför följande påståenden:
double x = Math. sqrt (-50); // Inte ett tal
dubbel y = x;
om (x == y)
System. ut. println ("x är lika med y");
Den resulterande konsolutgången är
Infinity
Om
i
var
-50. 0
, skulle konsolen visa
-Infinitet
, och om
i
var noll, skulle konsolen visa
NaN
.
Följande stycken beskriver några sista bitar av konstighet:
-
NaN
är inte lika med sig själv, vilket kan ha några märkliga konsekvenser. Till exempel:
dubbel x = matematik. sqrt (-50); // Inte ett tal
dubbel y = x;
om (x == y)
System. ut. println ("x är lika med y");
Tänk på att argumentet
om
testar om variabeln
x
är lika med variabeln
y
. Eftersom detta test omedelbart följer ett uppdragsförklaring som tilldelar värdet
x
till
y
, kan du säkert anta att
x
är lika med
y
, höger?
Fel. Eftersom
x
är
NaN
,
y
också är
NaN
.
NaN
anses aldrig vara lika med något annat värde, inklusive en annan
NaN
. Således misslyckas jämförelsen i
om
-satsen.
- En annan märklig konsekvens: Man kan inte anta att ett tal minus sig själv alltid är noll. Tänk på detta uttalande:
double z = x - x; // inte nödvändigtvis noll
Bör inte detta uttalande alltid ställa in
z
till noll? Inte om
x
är
NaN
. I så fall är inte ett tal minus ett tal fortfarande ett tal.
- En mer konstig: En matematisk operation som involverar oändligheten resulterar i någon annan oändlighet eller
NaN
. Infinity + 5, till exempel, är fortfarande lika med oändlighet, så Buzz Lightyears samtal "Till oändlighet och bortom! "Kommer bara inte att hända. Men oändlighet minus oändlighet ger dig …NaN
.