logo

Заокруживање грешака у Јави

Сажимање многих бесконачних реалних бројева у коначан број битова захтева приближну репрезентацију. Већина програма чува резултате целобројних рачунања на 32 или 64 бита максимално. С обзиром на било који фиксни број битова, већина прорачуна са реалним бројевима ће произвести количине које се не могу тачно представити користећи толико битова. Због тога се резултат израчунавања са помичним зарезом често мора заокружити да би се вратио у своју коначну репрезентацију. Ова грешка заокруживања је карактеристична карактеристика израчунавања са помичним зарезом. Стога, док рукујемо прорачунима у бројевима са покретним зарезом (посебно ако су прорачуни у новцу) морамо да водимо рачуна о грешкама заокруживања у програмском језику. Хајде да видимо пример:

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


поређење лава и тигра

Излаз:



x = 0.7999999999999999  
y = 0.8
false

Овде одговор није оно што смо очекивали, разлог је заокруживање које је урадио јава компајлер.

Разлог за грешку заокруживања

Типови података Флоат и Доубле имплементирају ИЕЕЕ 754 спецификацију са помичним зарезом. То значи да су бројеви представљени у облику као што је:

SIGN FRACTION * 2 ^ EXP 

0,15625 = (0,00101)2који је у формату са покретним зарезом представљен као: 1.01 * 2^-3
Не могу се сви разломци тачно представити као разломак степена два. Као једноставан пример 0,1 = (0,000110011001100110011001100110011001100110011001100110011001…)2 и стога се не може чувати унутар променљиве са помичним зарезом.

Други пример:

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

Излаз:

x = 0.7999999999999999  
y = 0.8
false

Други пример:

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

Излаз:

a = 0.09999999999999998

Како исправити грешке заокруживања?

  • Заокружите резултат: Функција Роунд() се може користити за минимизирање било каквих ефеката нетачности аритметичког складиштења са плутајућим зарезом. Корисник може заокружити бројеве на број децималних места који је потребан за прорачун. На пример, док радите са валутом, вероватно бисте заокружили на 2 децимале.
  • Алгоритми и функције: Користите нумерички стабилне алгоритме или дизајнирајте сопствене функције за руковање таквим случајевима. Можете скратити/заокружити цифре за које нисте сигурни да су тачне (можете израчунати и нумеричку прецизност операција)
  • БигДецимал Цласс: Можете користити јава.матх.БигДецимал класа која је дизајнирана да нам пружи тачност посебно у случају великих разломака. Следећи програм показује како се грешка може уклонити:
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);  } } 


Излаз:

0.1

Ево а = а.сетСцале(1 РоундингМоде.ХАЛФ_УП);

Роундс aна 1 децимално место користећи ХАЛФ_УП режим заокруживања. Дакле, коришћење БигДецимал-а пружа прецизнију контролу над аритметичким операцијама и операцијама заокруживања што може бити посебно корисно за финансијске прорачуне или друге случајеве где је прецизност кључна.

Важна напомена:

Матх.роунд заокружује вредност на најближи цео број. Како је 0,10 ближе 0 него 1, заокружује се на 0. Након заокруживања и дељења са 1,0 резултат је 0,0. Тако можете приметити разлику између излаза са БигДецимал класом и Матхс.роунд функцијом.

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

Излаз:

0.0