Java十六进制浮点文字
我如何遇到十六進制浮點數(shù)
我正在Java :: Geci中開發(fā)一種新功能,以減少代碼重新格式化的可能性。 如果重新格式化,當前版本的代碼將覆蓋原本相同的代碼。 這很煩人,因為按下重新格式化鍵的快捷鍵相當容易,而且許多項目甚至要求開發(fā)人員將其編輯器設(shè)置為在保存時自動格式化代碼。 在這種情況下,不能使用Java :: Geci,因為一旦重新格式化了代碼,生成器就會認為生成的代碼與源文件中已經(jīng)存在的代碼不同,會對其進行更新并發(fā)出代碼更改失敗的信號。單元測試。
我正在設(shè)計的解決方案首先將Java源文件進行比較,然后將其轉(zhuǎn)換為詞匯元素列表。 這樣,只要代碼保持不變,您甚至可以重新格式化插入換行符,空格等的代碼。 為此,我需要一個簡化的Java詞法分析器。 編寫詞法分析器沒什么大不了的,自從我在1987年首次閱讀《 龍書》以來,我出于不同的原因創(chuàng)建了多個詞法分析器。我真正需要的唯一是精確定義字符串,字符,數(shù)字文字,關(guān)鍵字和以此類推。 簡而言之:Java語言在詞匯級別上的定義是什么以及如何處理。 幸運的是,對此有一個精確的定義,即Java語言規(guī)范 ,它不僅精確而且可讀,并帶有示例。 因此,我開始閱讀相應(yīng)的章節(jié)。
令我感到困惑的是,我可以看到Java語言中有可能用十六進制表示浮點數(shù)。 奇怪嗎 由于我從未見過它,所以我首先以為這是Java 12中引入的新內(nèi)容,但我的調(diào)查表明它可能是在Java 1.5中引入的。那是我真正喜歡的第一個Java版本,但不是因為十六進制浮點數(shù)。 所以這就是我面對面遇到這只野獸的方式。 我開始懷疑這頭野獸是否可以在野外找到,還是只能在JLS文本范圍內(nèi)被俘虜?shù)臇|西。 所以…
我在Twitter上投票
如您所見,九個人面的人回答了這個問題,主要是說他們對這個功能一無所知。
在lambda和流之后,可能十六進制浮點數(shù)是Java語言中鮮為人知和使用最少的功能(開個玩笑……十六進制浮點數(shù)很重要,對嗎?)
即使我過去做過一些科學研究,也看不到十六進制浮點字面量的任何使用。
什么是浮點數(shù)?
我們將使用十六進制浮點數(shù),但要了解我們必須首先知道什么是浮點數(shù)。
浮點數(shù)具有尾數(shù)和指數(shù)。 尾數(shù)具有整數(shù)和小數(shù)部分,例如iii.ffff 。 指數(shù)是整數(shù)。 例如,31.415926E-1是浮點數(shù),是圓的直徑和周長之比的近似值。
Java內(nèi)部將float存儲在32位上 ,將double float數(shù)存儲在64位上 。 實際比特根據(jù)IEEE 754標準使用。
這樣,這些位將符號存儲在單個位上,然后將指數(shù)存儲在8位或11位上,最后將尾數(shù)存儲在23位或52位上,分別用于32位或64位浮點/雙精度。 尾數(shù)是一個小數(shù),其值在1到2之間。這可以用位流表示,其中第一位表示1,第二位表示1/2,依此類推。 但是,由于該數(shù)字始終以規(guī)范化存儲,因此該數(shù)字始終在[1和2之間],因此第一位始終為1。無需存儲它。 存儲尾數(shù),以便最高有效位表示1/2,下一個1/2 2以此類推,但是當我們需要該值時,將其加1。
尾數(shù)是無符號的(因此我們有一個單獨的signum位)。 指數(shù)也是無符號的,但是計算出的實際移位數(shù)是從該值中減去127或1023以獲得有符號數(shù)。 它指定尾數(shù)實際上應(yīng)向左或向右移動多少位。 因此,當我們寫31.415926E-1f ,指數(shù)將不是-1。 那是數(shù)字的十進制格式。
實際值為01000000010010010000111111011010 。 分解:
- 0號,數(shù)字為正。 到目前為止,一切都很好。
- 10000000 128,這意味著我們必須將尾數(shù)左移一位(該值乘以2)
- 10010010000111111011010是 。 該位流的十六進制表示為0x490FDA
這是
十六進制浮點文字
我們可以在Java中編寫與0x0.C90FDAP2f相同的數(shù)字。 這是相同數(shù)字的十六進制浮點表示形式。
尾數(shù)0xC9aFDA應(yīng)該熟悉0x490FDA以上數(shù)字的十六進制表示0x490FDA 。 不同之處在于,第一個字符是C而不是4 。 那是額外的一位,始終為1,不存儲在二進制表示中。 C是1100而原始4是0100 。 指數(shù)是將數(shù)字推到正確位置所需的實際位移的帶符號十進制表示形式。
文字的格式并非無關(guān)緊要。 首先,您必須使用指數(shù)部分,并且指數(shù)的字符為p或P 這與十進制表示形式有很大不同。 (更新:如果指數(shù)是可選的,則您無法確定例如0.55是十進制浮點還是十六進制浮點。十六進制數(shù)字偶然可以僅包含十進制字符,而仍然是十六進制。)
經(jīng)過一番思考,很明顯無法使用常規(guī)e或E來表示指數(shù),因為該字符是合法的十六進制數(shù)字,并且在數(shù)字(如0x2e3情況下可能會模棱兩可。 這是十六進制整數(shù)還是。 這是整數(shù),因為我們使用p而不是e 。
我只能猜測為什么指數(shù)部分是強制性的。 因為開發(fā)人員已經(jīng)習慣使用e或E作為指數(shù)來十進制浮點數(shù),所以很容易將0xC90F.0e+3誤讀為單個浮點數(shù),即使需要十六進制浮點p而不是e 。 如果指數(shù)不是強制性的,則此示例將是浮點數(shù)與整數(shù)的合法和。 同時看起來像一個數(shù)字,那不是很好。
另一個有趣的事情是指數(shù)是十進制。 這也是因為某些十六進制數(shù)字已被用于其他目的。 浮點數(shù)和雙后綴。 如果要表示文字是浮點數(shù),則可以將f或F附加到末尾。 如果要表示此文字為double,則可以將d或D附加到末尾。 這是默認設(shè)置,因此添加D是可選的。 如果指數(shù)是十六進制的,我們將不知道0x32.1P1f是浮點文字還是雙精度數(shù),并且具有很多大小不同的值。 這樣,那個指數(shù)是十進制,它是一個浮點數(shù)。
Java和IEEE 754
Java在Java 1.2之前一直嚴格執(zhí)行IEEE 754標準,該標準不僅定義了存儲在內(nèi)存中的數(shù)字格式,而且還定義了應(yīng)如何執(zhí)行計算的規(guī)則。 Java 1.2版(包括1.2版)之后,發(fā)布了該標準以使實現(xiàn)更加自由,從而允許使用更多的位來存儲中間結(jié)果。 它曾經(jīng)并且仍然可以在Intel CPU平臺上使用,并且在諸如FORTRAN之類的其他語言的數(shù)值計算中被大量使用。 這是允許實現(xiàn)使用更高精度的邏輯步驟。
為了保持向后兼容性,同時在語言中添加了strictfp修飾符。 在類,接口或方法上使用此修飾符時,這些代碼中的浮點計算將嚴格遵循IEEE 754標準。
帶走
- Java中有十六進制浮點文字。 記住它以及strictfp是什么,因為有人可能在Java采訪中問您有關(guān)它的問題。 在企業(yè)編程中沒有實際用途。
- 除非使代碼更具可讀性,否則不要使用它們。 我?guī)缀鯚o法想象會發(fā)生這種情況的任何情況。 因此,簡而言之:不要僅僅因為可以就使用它們。
- 在Twitter @verhas上關(guān)注我,以獲取有關(guān)新文章的通知。
關(guān)注@verhas
我認為僅此而已。 在本文發(fā)表時,我可能會和一萬人一起在蘇黎世湖中游泳。 這是一個大事件。
哦……是的:如果您曾經(jīng)在Java中使用十六進制浮點文字來使其更具可讀性,請在注釋中分享知識。 我敢于以讀者的名義說:我們很感興趣。
更新:約瑟夫·達西(Joseph Darcy)(Oracle的工程師,OpenJDK開發(fā)人員,馬拉松運動員,快步手,偶爾的攝影師,還有很多其他事情。)在Twitter上提供了反饋。 我將他的回復(fù)復(fù)制到這里,因為它絕對有價值,并為讀者增加了價值,從而使讀者受益:
十進制字符串和二進制浮點值的特定設(shè)置之間的映射通常是不明顯的。 十六進制浮點文字在需要時(例如在測試中)提供了直接的文本到二進制fp映射。 參見https://blogs.oracle.com/darcy/hexadecimal-floating-point-literals
翻譯自: https://www.javacodegeeks.com/2019/07/java-hexadecimal-floating-point-literal.html
總結(jié)
以上是生活随笔為你收集整理的Java十六进制浮点文字的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: lombok 生成代码_使用Projec
- 下一篇: java学习里程碑_记录您的里程和社区运