logo

Avrunding av feil i Java

Å komprimere mange uendelige reelle tall til et endelig antall biter krever en omtrentlig representasjon. De fleste programmer lagrer resultatet av heltallsberegninger med maks 32 eller 64 biter. Gitt et hvilket som helst fast antall biter vil de fleste beregninger med reelle tall produsere mengder som ikke kan representeres nøyaktig ved å bruke så mange biter. Derfor må resultatet av en flyttallsberegning ofte avrundes for å passe tilbake til dens endelige representasjon. Denne avrundingsfeilen er et karakteristisk trekk ved flytepunktberegning. Derfor, mens vi håndterer beregninger i flyttall (spesielt hvis beregninger er i form av penger), må vi ta vare på avrundingsfeil i et programmeringsspråk. La oss se et eksempel:

Java
public class Main {  public static void main(String[] args)  {  double a = 0.7;  double b = 0.9;  double x = a + 0.1;  double y = b - 0.1;  System.out.println('x = ' + x);  System.out.println('y = ' + y );  System.out.println(x == y);  } } 


kamelvesken python

Produksjon:



x = 0.7999999999999999  
y = 0.8
false

Her er ikke svaret det vi forventet grunnen til å være avrundingen gjort av java-kompilatoren.

Årsak bak avrundingsfeil

Float- og Double-datatyper implementerer IEEE-floating point 754-spesifikasjonen. Dette betyr at tall er representert i en form som:

SIGN FRACTION * 2 ^ EXP 

0,15625 = (0,00101)2som i flyttallformat er representert som: 1,01 * 2^-3
Ikke alle brøker kan representeres nøyaktig som en brøkdel av en potens av to. Som et enkelt eksempel 0,1 = (0,000110011001100110011001100110011001100110011001100110011001…)2 og kan derfor ikke lagres inne i en flyttallsvariabel.

Et annet eksempel:

java
public class Main {  public static void main(String[] args)  {  double a = 0.7;  double b = 0.9;  double x = a + 0.1;  double y = b - 0.1;  System.out.println('x = ' + x);  System.out.println('y = ' + y );  System.out.println(x == y);  } } 

Produksjon:

x = 0.7999999999999999  
y = 0.8
false

Et annet eksempel:

Java
public class Main {  public static void main(String args[])  {  double a = 1.0;  double b = 0.10;  double x = 9 * b;  a = a - (x);  // Value of a is expected as 0.1  System.out.println('a = ' + a);  } } 

Produksjon:

a = 0.09999999999999998

Hvordan rette opp avrundingsfeil?

  • Rund resultatet: Round()-funksjonen kan brukes til å minimere eventuelle effekter av aritmetisk lagringsunøyaktighet med flyttall. Brukeren kan avrunde tall til antall desimaler som kreves av beregningen. For eksempel når du arbeider med valuta, vil du sannsynligvis runde av til 2 desimaler.
  • Algoritmer og funksjoner: Bruk numerisk stabile algoritmer eller design dine egne funksjoner for å håndtere slike tilfeller. Du kan avkorte/avrunde sifre som du ikke er sikker på om er riktige (du kan også beregne numerisk presisjon for operasjoner)
  • BigDesimal Class: Du kan bruke java.math.BigDecimal klasse som er designet for å gi oss nøyaktighet, spesielt i tilfelle store brøktall. Følgende program viser hvordan feilen kan fjernes:
Java
import java.math.BigDecimal; import java.math.RoundingMode; public class Main {  public static void main(String args[]) {  BigDecimal a = new BigDecimal('1.0');  BigDecimal b = new BigDecimal('0.10');  BigDecimal x = b.multiply(new BigDecimal('9'));  a = a.subtract(x);  // Rounding to 1 decimal place  a = a.setScale(1 RoundingMode.HALF_UP);  System.out.println('a = ' + a);  } } 


Produksjon:

0.1

Her a = a.setScale(1 RoundingMode.HALF_UP);

runder atil 1 desimal ved å bruke HALF_UP avrundingsmodus. Så bruk av BigDecimal gir mer presis kontroll over aritmetikken og avrundingsoperasjonene, noe som kan være spesielt nyttig for økonomiske beregninger eller andre tilfeller der presisjon er avgjørende.

Viktig merknad:

Math.round runder av verdien til nærmeste heltall. Ettersom 0,10 er nærmere 0 enn 1, avrundes det til 0. Etter avrunding og divisjon med 1,0 er resultatet 0,0. Så du kan merke forskjellen mellom utdataene med BigDecimal-klassen og Maths.round-funksjonen.

Java
public class Main {  public static void main(String args[])  {  double a = 1.0;  double b = 0.10;  double x = 9 * b;  a = a - (x);  /* We use Math.round() function to round the answer to  closest long then we multiply and divide by 1.0 to  to set the decimal places to 1 place (this can be done  according to the requirements.*/  System.out.println('a = ' + Math.round(a*1.0)/1.0);  } } 

Produksjon:

0.0