logo

Afrunding af fejl i Java

At komprimere mange uendelige reelle tal til et endeligt antal bit kræver en omtrentlig repræsentation. De fleste programmer gemmer resultatet af heltalsberegninger ved maks. 32 eller 64 bit. Givet et hvilket som helst fast antal bits vil de fleste beregninger med reelle tal producere mængder, der ikke kan repræsenteres nøjagtigt ved brug af så mange bits. Derfor skal resultatet af en flydende kommaberegning ofte afrundes for at passe tilbage til dens endelige repræsentation. Denne afrundingsfejl er et karakteristisk træk ved flydende kommaberegning. Derfor er vi nødt til at tage hånd om afrundingsfejl i et programmeringssprog, mens vi håndterer beregninger i flydende kommatal (især hvis beregninger er i form af penge). Lad os 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);  } } 


kamelhylster python

Produktion:



x = 0.7999999999999999  
y = 0.8
false

Her er svaret ikke, hvad vi forventede grunden til afrundingen udført af java compiler.

Årsag bag afrundingsfejl

Float- og Double-datatyper implementerer IEEE-floating point 754-specifikationen. Det betyder, at tal er repræsenteret i en form som:

SIGN FRACTION * 2 ^ EXP 

0,15625 = (0,00101)2som i flydende kommaformat er repræsenteret som: 1,01 * 2^-3
Ikke alle brøker kan repræsenteres nøjagtigt som en brøkdel af en potens af to. Som et simpelt eksempel 0,1 = (0,000110011001100110011001100110011001100110011001100110011001…)2 og kan derfor ikke gemmes inde i en variabel med flydende komma.

Et andet 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);  } } 

Produktion:

x = 0.7999999999999999  
y = 0.8
false

Et andet 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);  } } 

Produktion:

a = 0.09999999999999998

Hvordan rettes afrundingsfejl?

  • Afrund resultatet: Funktionen Round() kan bruges til at minimere eventuelle effekter af aritmetisk lagerunøjagtighed med flydende komma. Brugeren kan afrunde tal til det antal decimaler, der kræves af beregningen. For eksempel, mens du arbejder med valuta, vil du sandsynligvis afrunde til 2 decimaler.
  • Algoritmer og funktioner: Brug numerisk stabile algoritmer eller design dine egne funktioner til at håndtere sådanne sager. Du kan afkorte/afrunde cifre, hvis du ikke er sikker på, at de er korrekte (du kan også beregne numerisk præcision af operationer)
  • BigDecimal Klasse: Du kan bruge java.math.BigDecimal klasse, som er designet til at give os nøjagtighed, især i tilfælde af store brøktal. Følgende program viser, hvordan fejlen 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);  } } 


Produktion:

0.1

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

runder atil 1 decimal ved at bruge HALF_UP afrundingstilstand. Så brug af BigDecimal giver mere præcis kontrol over aritmetikken og afrundingsoperationerne, hvilket kan være særligt nyttigt til økonomiske beregninger eller andre tilfælde, hvor præcision er afgørende.

Vigtig bemærkning:

Math.round afrunder værdien til nærmeste heltal. Da 0,10 er tættere på 0 end på 1, bliver det afrundet til 0. Efter afrunding og division med 1,0 er resultatet 0,0. Så du kan bemærke forskellen mellem output med BigDecimal klasse og Maths.round funktion.

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);  } } 

Produktion:

0.0