Аритметика с плаваща запетая

Добре дошли в друга част от Under The Hood . Тази колона има за цел да даде на разработчиците на Java поглед върху скритата красота под техните работещи Java програми. Колоната от този месец продължава дискусията, започнала миналия месец, на набора от инструкции за байт кода на виртуалната машина Java (JVM). Тази статия разглежда аритметиката с плаваща запетая в JVM и обхваща байт кодовете, които извършват аритметични операции с плаваща запетая. Следващите статии ще обсъждат други членове на семейството на байт кодове.

Основните плаващи точки

Поддръжката на JVM с плаваща запетая се придържа към стандарта с плаваща запетая IEEE-754 1985. Този стандарт определя формата на 32-битовите и 64-битовите числа с плаваща запетая и определя операциите върху тези числа. В JVM аритметиката с плаваща запетая се извършва на 32-битови плувки и 64-битови двойни. За всеки байт код, който изпълнява аритметика на плувки, има съответен байт код, който извършва същата операция на двойни.

Числото с плаваща запетая има четири части - знак, мантиса, радикс и експонента. Знакът е или 1, или -1. Мантисата, винаги положително число, съдържа значимите цифри на числото с плаваща запетая. Показателят показва положителната или отрицателната сила на радикса, по който мантисата и знакът трябва да се умножат. Четирите компонента се комбинират, както следва, за да се получи стойността с плаваща запетая:

знак * мантиса * радикс експонента

Числата с плаваща запетая имат множество представления, тъй като винаги може да се умножи мантисата на всяко число с плаваща запетая по някаква степен на радикса и да се промени степента, за да се получи оригиналното число. Например числото -5 може да бъде представено еднакво от всяка от следните форми в радикс 10:

Форми на -5
Знак Мантиса Експонента на Radix
-1 50 10 -1
-1 5 10 0
-1 0,5 10 1
-1 0,05 10 2

За всяко число с плаваща запетая има едно представяне, за което се казва, че е нормализирано. Число с плаваща запетая се нормализира, ако неговата мантиса е в диапазона, определен от следната връзка:

1 / radix <= mantissa <

Нормализираното число с плаваща запетая radix 10 има десетичната си точка точно вляво от първата ненулева цифра в мантисата. Нормализираното представяне с плаваща запетая на -5 е -1 * 0,5 * 10 1. С други думи, мантисата на нормализирано число с плаваща запетая няма ненулеви цифри вляво от десетичната запетая и ненулева цифра само за вдясно от десетичната запетая. Всяко число с плаваща запетая, което не се вписва в тази категория, се счита за денормализирано . Обърнете внимание, че числото нула няма нормализирано представяне, тъй като няма ненулева цифра, която да се постави точно вдясно от десетичната запетая. „Защо да се нормализира?“ е често срещано възклицание сред нули.

Числата с плаваща запетая в JVM използват радикс от две. Следователно числата с плаваща запетая в JVM имат следната форма:

знак * мантиса * 2 експонента

Мантисата на число с плаваща запетая в JVM се изразява като двоично число. Нормализираната мантиса има своята двоична точка (еквивалент на два основни еквивалента на десетична точка) точно вляво от най-значимата ненулева цифра. Тъй като двоичната бройна система има само две цифри - нула и една - най-значимата цифра на нормализираната мантиса винаги е единица.

Най-значимият бит на флоат или дубъл е неговият знаков бит. Мантисата заема 23-те най-малко значими бита на плувка и 52-те най-малко значими бита на дубъл. Експонентата, 8 бита в плувка и 11 бита в двойна, се намира между знака и мантисата. Форматът на поплавъка е показан по-долу. Знаковият бит е показан като "s", битовете на степента са показани като "e", а битовете на мантисата са показани като "m":

Битово оформление на Java float
s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm

Знаков бит нула показва положително число, а знаков бит едно означава отрицателно число. Мантисата винаги се тълкува като положително число две. Това не е число с две допълнения. Ако знаковият бит е един, стойността с плаваща запетая е отрицателна, но мантисата все още се интерпретира като положително число, което трябва да се умножи по -1.

Експонентното поле се интерпретира по един от трите начина. Експонента на всички показва, че числото с плаваща запетая има една от специалните стойности на плюс или минус безкрайност, или "не число" (NaN). NaN е резултат от определени операции, като разделяне на нула на нула. Експонента на всички нули показва денормализирано число с плаваща запетая. Всеки друг показател показва нормализирано число с плаваща запетая.

Мантисата съдържа един допълнителен бит прецизност извън тези, които се появяват в битовете на мантисата. Мантисата на плувка, която заема само 23 бита, има 24 бита прецизност. Мантисата на двойник, която заема 52 бита, има 53 бита прецизност. Най-значимият бит на мантиса е предсказуем и следователно не е включен, тъй като степента на числата с плаваща запетая в JVM показва дали броят е нормализиран или не. Ако степента е всички нули, числото с плаваща запетая се денормализира и най-значимият бит на мантисата е нула. В противен случай числото с плаваща запетая се нормализира и най-значимият бит на мантисата е известен като един.

JVM не създава изключения в резултат на операции с плаваща запетая. Специални стойности, като положителна и отрицателна безкрайност или NaN, се връщат в резултат на подозрителни операции като разделяне на нула. Експонента на всички показва специална стойност с плаваща запетая. Експонента на всички с мантиса, чиито битове са нула, показва безкрайност. Знакът на безкрайността се обозначава със знаковия бит. Експонента на всички с която и да е друга мантиса се тълкува като "не число" (NaN). JVM винаги произвежда една и съща мантиса за NaN, която е всички нули, с изключение на най-значимия бит на мантиса, който се появява в числото. Тези стойности са показани за поплавък отдолу:

Специални плаващи стойности
Стойност Плаващи битове (знак за степен на мантиса)
+ Безкрайност 0 11111111 00000000000000000000000
-Безкрайност 1 11111111 00000000000000000000000
NaN 1 11111111 10000000000000000000000

Експонентите, които не са нито единици, нито всички нули, показват силата на две, по които да се умножи нормализираната мантиса. Степента на две може да бъде определена чрез интерпретиране на битите на степента като положително число и след това изваждане на пристрастие от положителното число. За поплавък пристрастието е 126. За двойно отклонението е 1023. Например, експонентно поле в поплавък от 00000001 дава степен на две чрез изваждане на пристрастието (126) от експонентното поле, интерпретирано като положително цяло число (1). Следователно мощността на двама е 1 - 126, което е -125. Това е най-малката възможна мощност от две за поплавък. В другата крайност, експонентно поле от 11111110 дава степен на две от (254 - 126) или 128. Числото 128 е най-голямата степен от две, налични за поплавък. Няколко примера за нормализирани плувки са показани в следващата таблица:

Нормализирани плаващи стойности
Стойност Плаващи битове (знак за степен на мантиса) Безпристрастен експонент
Най-големият положителен (краен) поплавък 0 11111110 11111111111111111111111 128
Най-големият отрицателен (краен) плувка 1 11111110 11111111111111111111111 128
Най-малката нормализирана плувка 1 00000001 00000000000000000000000 -125
Пи 0 10000000 10010010000111111011011 2

Експонента на всички нули показва, че мантисата е денормализирана, което означава, че нестатираният водещ бит е нула вместо единица. Силата на две в този случай е същата като най-ниската мощност на две, налична за нормализирана мантиса. За поплавъка това е -125. Това означава, че нормализираните мантиси, умножени по две, издигнати в степен -125, имат експонентно поле 00000001, докато денормализираните мантиси, умножени по две, вдигнати в степен -125, имат експонентно поле 00000000. Разрешението за денормализираните числа в долната част края на диапазона от експоненти поддържа постепенно преливане. Ако вместо това се използва най-ниският експонентен коефициент за представяне на нормализирано число, при по-големи числа ще се получи понижаване до нула. С други думи, оставянето на най-ниския степен на денормализирани числа позволява да се представят по-малки числа.По-малките денормализирани числа имат по-малко битове прецизност от нормализираните числа, но това е за предпочитане да се прелива до нула веднага щом степента достигне минималната си нормализирана стойност.

Денормализирани плаващи стойности
Стойност Плаващи битове (знак за степен на мантиса)
Най-малкият положителен (ненулев) плувка 0 00000000 00000000000000000000001
Най-малкият отрицателен (ненулев) плувка 1 00000000 00000000000000000000001
Най-големият денормализиран поплавък 1 00000000 11111111111111111111111
Положителна нула 0 00000000 00000000000000000000000
Отрицателна нула 1 00000000 00000000000000000000000

Изложена плувка

Поплавъкът на Java разкрива вътрешната си същност Аплетът по-долу ви позволява да играете с формата с плаваща запетая. Стойността на float се показва в няколко формата. Форматът за научна нотация на radix two показва мантисата и експонента в основата десет. Преди да бъде показана, действителната мантиса се умножава по 2 24, което дава интегрално число, а непредубеденият експонент се намалява с 24. И двете интегрални мантиса и експонента след това лесно се преобразуват в база десет и се показват.