Indholdsfortegnelse:
Video: String Theory Explained – What is The True Nature of Reality? 2025
Tro det eller ej, computere - selv de mest kraftfulde - har visse begrænsninger, når det kommer til at udføre matematiske beregninger. Disse begrænsninger er normalt ubetydelige, men nogle gange sniger de sig op og bider dig. Her er de ting du skal passe på, når du laver matematik i Java.
Integer overløb
Det grundlæggende problem med heltalstyper er, at de har en fast størrelse. Som følge heraf er der en grænse for størrelsen på de tal, der kan gemmes i variabler af typen
kort
,
int
eller
lang
. Selvom
lange
-variabler kan indeholde tal, der er store, kommer du før eller senere over et tal, der er for stort til at passe ind i en
lang
variabel.
Okay, overvej dette (admittedly contrived) eksempel:
int a = 1000000000;
System. ud. println (a);
a + = 1000000000;
System. ud. println (a);
a + = 1000000000;
System. ud. println (a);
a + = 1000000000;
System. ud. println (a);
Her forventer du værdien af
a
for at blive større efter hver tilføjelse. Men her er det output, der vises:
1000000000
2000000000
-1294967296
-294967296
Den første tilføjelse ser ud til at fungere, men efter dette bliver nummeret negativt! Det skyldes, at værdien har nået størrelsesgrænsen for datatypen
int
. Desværre siger Java ikke dig, at denne fejl er sket. Den smækker bare
int
-variablen som fuld af bits som det kan, kasserer det, der ikke passer, og håber, at du ikke mærker. På grund af måden
int
opbevares negative værdier, bliver store positive værdier pludselig store negative negative værdier.
Historien er, at hvis du arbejder med store heltal, skal du bruge
lang
i stedet for
int
, fordi
lang
kan lagre meget større tal end
int
. Hvis dine programmer omhandler tal, der er store nok til at være et problem for
lang
, skal du overveje at bruge floating-point-typer i stedet. Flydende typer kan håndtere endnu større værdier end
lang
, og de fortæller dig, når du overskrider deres kapacitet.
Floating Point Weirdness
Flydende punktnumre har egne problemer. Til at begynde med opbevares flytende punktnumre ved hjælp af det binære talesystem (base 2), men mennesker arbejder med tal i decimaltalsystemet (base 10). Desværre er nøjagtigt konvertering af tal mellem disse to systemer undertiden umuligt. Det skyldes, at i enkelte talbaser kan visse fraktioner ikke repræsenteres nøjagtigt.
Et eksempel: Base 10 har ingen måde at præcis repræsentere fraktionen 1/3. Du kan tilnærme det som 0. 3333333, men i sidste ende når du grænsen for hvor mange cifre du kan gemme, så du skal stoppe. I base 2 sker det, at en af de fraktioner, du ikke kan repræsentere korrekt, er decimalværdien 1/10. Med andre ord kan en
float
eller
dobbelt
variabel ikke repræsentere nøjagtigt
0. 1
.
Prøv at køre denne kode:
float x = 0. 1f;
NumberFormat nf = NumberFormat. getNumberInstance ();
nf. setMinimumFractionDigits (10);
System. ud. println (nf. format (x));
Det resulterende output er dette:
0. 1000000015
Selvom
0. 1000000015
er tæt til
0. 1
, er det ikke nøjagtigt.
I de fleste tilfælde er Java's floating-point-matematik tæt nok ikke for noget. Fejlmarginen er ekstremt lille. Hvis du bruger Java til at måle størrelsen af dit hus, ville du have brug for et elektronmikroskop for at lægge mærke til fejlen. Hvis du skriver applikationer, der omhandler finansielle transaktioner, kan normal afrunding undertiden forstørre fejlene for at gøre dem væsentlige. Du kan opkræve en øre for meget eller for lidt moms. Og i ekstreme tilfælde kan dine fakturaer faktisk have indlysende additionsfejl.
Selvfølgelig er også heltaletyper gemt i binære. Men heltal er ikke underlagt de samme fejl, som floating-point-typer er - fordi heltal ikke repræsenterer fraktioner overhovedet - så du behøver ikke bekymre dig om denne type fejl for
heltal
typer.
Division med nul
Ifølge de grundlæggende regler for matematik kan du ikke dividere et tal med nul. Årsagen er enkel: Division er den omvendte multiplikation - hvilket betyder, at hvis
a * b = c
, er det også sandt, at
a = c / b
. Hvis du ville tillade
b
at være nul, ville division være meningsløs, fordi ethvert antal gange nul er nul. Derfor skal både
a
og
c
også være nul. Kort sagt, matematikere løst dette dilemma for århundreder siden ved at sige, at division med nul simpelthen ikke er tilladt.
Så hvad sker der, hvis du gør forsøg på at dele et nummer med nul i et Java-program? Svaret afhænger af, om du deler heltal eller flydende punktnumre. Hvis du deler heltal, sætter den sætning, der forsøger divisionen med nul, op, hvad der kaldes en undtagelse,, som er en uhyrlig måde at nedbryde programmet på.
Der er en måde at aflytte denne undtagelse for at lade dit program fortsætte, som du ikke kan finde ud af her. I mellemtiden vil ethvert program du skriver, forsøger et heltal division ved nulbrud.
Hvis du forsøger at opdele en flydende punkttype med nul, er resultaterne ikke så pludselige. I stedet tildeler Java til det flytende punktresultat en af de specielle værdier, der er angivet i tabellen nedenfor. Følgende afsnit forklarer, hvordan disse særlige værdier bestemmes:
- Hvis du deler et tal med nul, og tegnet på begge tal er det samme, er resultatet en positiv uendelighed.
0. 0
divideret med0. 0
er positiv uendelighed, som det er-34. 0
divideret med-0. 0
. - Hvis du deler et tal med nul, og tegnene på tallene er forskellige, er resultatet negativt uendeligt.
-40. 0
divideret med0. 0
er negativ uendelighed, som det er34. 0
divideret med0. 0
. - Hvis du deler nul med nul, er resultatet ikke et tal (NaN), uanset tegnene.
Konstant | Betydning |
POSITIVE_INFINITY
|
Positiv uendelighed |
NEGATIVE_INFINITY
|
Negativ uendelighed |
NaN
|
Ikke et tal |
Flydende punkt nuller kan være positive eller negative. Java anser positive og negative nuller for at være lige numerisk.
Hvis du forsøger at udskrive en flydende punktværdi, der har en af disse specielle værdier, konverterer Java værdien til en passende streng. Antag at du udfører følgende udsagn:
double x = Math. sqrt (-50); // Ikke et tal
dobbelt y = x;
hvis (x == y)
System. ud. println ("x er lig med y");
Den resulterende konsoludgang er
Uendelig
Hvis
i
var
-50. 0
, vil konsollen vise
-Infinitet
, og hvis
i
var nul, vil konsollen vise
NaN
.
De følgende afsnit beskriver nogle endelige bitterheder:
-
NaN
er ikke lig med sig selv, hvilket kan have nogle mærkelige konsekvenser. For eksempel:
dobbelt x = matematik. sqrt (-50); // Ikke et tal
dobbelt y = x;
hvis (x == y)
System. ud. println ("x er lig med y");
Tænk for argumentets skyld, at
hvis
erklæringen tester om variablen
x
er lig med variablen
y
. Fordi denne test straks følger en opgaveopgørelse, der tildeler værdien
x
til
y
, kan du med sikkerhed antage at
x
er lig med
y
, højre?
Forkert. Fordi
x
er
NaN
,
y
også er
NaN
.
NaN
anses aldrig for at være lig med nogen anden værdi, herunder en anden
NaN
. Således mislykkes sammenligningen i
hvis
sætningen.
- En anden underlig konsekvens: Du kan ikke antage, at et tal minus sig selv altid er nul. Overvej denne erklæring:
double z = x - x; // ikke nødvendigvis nul
Skal ikke denne erklæring altid sætte
z
til nul? Ikke hvis
x
er
NaN
. I så fald er ikke et tal minus et tal stadig et tal.
- En anden underlighed: Enhver matematisk operation, der involverer uendelig, resulterer i enten en anden uendelighed eller
NaN
. Infinity + 5, for eksempel, er stadig lig med uendelighed, så Buzz Lightyears kald "Til uendelig og videre! "Det kommer bare ikke til at ske. Men uendelighed minus uendelighed giver dig …NaN
.