1. Закръгляване на реални числа

Както вече обсъдихме, когато реално число е присвоено на променлива int, то винаги се закръгля надолу до най-близкото по-малко цяло число — дробната част просто се изхвърля.

Но е лесно да си представим ситуация, когато дробно число трябва да бъде закръглено до най-близкото цяло число в която и да е посока or дори закръглено нагоре. Какво правите в този случай?

За тази и за много подобни ситуации Java има Mathклас, който има методите round(), ceil()и floor().


Math.round()метод

Методът Math.round()закръгля число до най-близкото цяло число:

long x = Math.round(real_number)

Но тук има още един нюанс: този метод връща цяло longчисло (а не int). Тъй като реалните числа могат да бъдат много големи, създателите на Java решиха да използват най-големия наличен целочислен тип на Java: long.

Съответно, ако програмист иска да присвои резултата на променлива int, тогава той трябва изрично да посочи на компилатора, че приема възможната загуба на данни (в случай, че полученото число не се вписва в тип int).

int x = (int) Math.round(real_number)

Примери:

Изявление Резултат
int x = (int) Math.round(4.1);
4
int x = (int) Math.round(4.5);
5
int x = (int) Math.round(4.9);
5

Math.ceil()метод

Методът Math.ceil()закръгля число до цяло число. Ето примери:

Изявление Резултат
int x = (int) Math.ceil(4.1);
5
int x = (int) Math.ceil(4.5);
5
int x = (int) Math.ceil(4.9);
5

Math.floor()метод

Методът Math.floor()закръгля число надолу до цяло число. Ето примери:

Изявление Резултат
int x = (int) Math.floor(4.1);
4
int x = (int) Math.floor(4.5);
4
int x = (int) Math.floor(4.9);
4

Разбира се, когато закръгляте число надолу до цяло число, е по-лесно просто да използвате оператор за преобразуване на типа:(int)

Изявление Резултат
int x = (int) 4.9
4

Ако ви е трудно да запомните тези имена, кратък урок по английски ще ви помогне:

  • Mathозначава математика
  • Roundозначава кръгло
  • Ceilingозначава таван
  • Floorозначава под

2. Как са структурирани числата с плаваща запетая

Типът doubleможе да съхранява стойности в диапазона от до . Този огромен диапазон от стойности (в сравнение с типа) се обяснява с факта, че типът (Howто и ) има напълно различна вътрешна структура от целочислените типове. Вътрешно типът codeира стойността си като две числа: първото се нарича мантиса , а второто се нарича експонента .-1.7*10308+1.7*10308intdoublefloatdouble

Да кажем, че имаме числото 123456789и го съхраняваме като doubleпроменлива. Когато го направим, числото се преобразува в , а вътрешно типът съхранява две числа — и . Значимото ("значимата част от числото" or мантисата) е подчертано в червено, докато показателят е подчертано в синьо.1.23456789*108double234567898

Този подход позволява да се съхраняват Howто много големи числа, така и много малки. Но тъй като представянето на числото е ограничено до 8 byteа (64 бита) и някои от битовете се използват за съхраняване на експонентата (Howто и знака на мантисата и знака на експонентата), максималните налични цифри за представяне на мантисата е 15 .

Това е много опростено описание на това How са структурирани реалните числа.


3. Загуба на точност при работа с реални числа

Когато работите с реални числа, винаги имайте предвид, че реалните числа не са точни . Винаги може да има грешки при закръгляване и грешки при преобразуване при преобразуване от десетична в двоична система. Освен това, най-често срещаният източник на грешка е загубата на точност при добавяне/изваждане на числа в коренно различни мащаби.

Последният факт е малко умопомрачителен за начинаещите програмисти.

Ако извадим от , получаваме .1/109109109

Изваждане на числа в коренно различни мащаби Обяснение
1000000000.000000000;
-         0.000000001;
 1000000000.000000000;
Второто число е изключително малко , което ще доведе до пренебрегване на неговия значим (маркиран в сиво). 15- те значещи цифри са подчертани в оранжево.

Какво да кажем, програмирането не е същото като математиката.


4. Клопка при сравняване на реални числа

Друга опасност дебне програмистите, когато сравняват реални числа. Възниква при работа с реални числа, защото могат да се натрупат грешки при закръгляне. Резултатът е, че има ситуации, когато реалните числа се очаква да бъдат равни, но не са. Или обратното: числата се очаква да са различни, но са равни.

Пример:

Изявление Обяснение
double a = 1000000000.0;
double b = 0.000000001;
double c = a - b;
Стойността на променливата a ще бъде 1000000000.0
Стойността на променливата c ще бъде 1000000000.0
(числото в b променливата е прекалено малко)

В горния пример aи cне трябва да са равни, но са.

Или нека вземем друг пример:

Изявление Обяснение
double a = 1.00000000000000001;
double b = 1.00000000000000002;
Стойността на променливата a ще бъде 1.0
Стойността на променливата b ще бъде1.0

5. Интересен факт заstrictfp

Java има специална strictfpключова дума ( strict f loating p point ), която не се среща в други езици за програмиране. И знаете ли защо ви трябва? Влошава точността на операциите с числа с плаваща запетая . Ето историята How се появи:

Създателите на Java:
Ние наистина искаме Java да бъде супер популярна и да изпълнява Java програми на възможно най-много устройства. Така че се уверихме, че спецификацията за Java машината казва, че всички програми трябва да работят по един и същи начин на всички видове устройства!
Производители на процесори Intel:
Здравейте на всички! Ние подобрихме нашите процесори и сега всички реални числа се представят с помощта на 10 byteа instead of 8 byteа в нашите процесори. Повече byteове означават повече значими цифри. Какво означава това? Това е вярно! Сега вашите научни изчисления ще бъдат още по-точни!
Учените и всички, които се занимават със свръхпрецизни изчисления:
Готино! Много добре. Отлична новина!
Създателите на Java:
Не-не-не, момчета! Вече ви казахме, че всички Java програми трябва да работят еднакво на всички устройства . Ще деактивираме принудително възможността за използване на 10-byteови реални числа в процесорите на Intel.
Сега всичко отново е наред! Не ни благодарете.
Учените и всички, които се занимават със свръхпрецизни изчисления:
Съвсем ли си полудял? Бързо върнете всичко Howто си беше!
Създателите на Java:
Момчета, това е за ваше добро! Само си представете: всички Java програми работят по един и същи начин на всички устройства . Това е толкова готино!
Учените и всички, които се занимават със свръхпрецизни изчисления:
Не, изобщо не е готино. Бързо върнете всичко Howто си беше! Или знаете къде ще поставим вашата Java?
Създателите на Java:
Хм. Защо не го каза веднага? Разбира се, ще го върнем обратно.
Ние възстановихме способността ви да използвате всички функции на най-новите процесори.
Между другото... Ние също така специално добавихме strictfpключовата дума към езика. Ако го напишете преди името на функция, тогава всички операции, включващи реални числа в тази функция, ще бъдат еднакво лоши на всички устройства !