printfの再実装をしたたかにやってみる(3)
まえおき
これはシリーズ記事です。
掲載するコードは説明のために書かれたものであり動作の保証はありません。また、完成形のコードは公開しません。ぜひご自身で書いてください。
long doubleとは
printfをわりとしっかり再実装してみる企画の第三回目。
doubleの表示を解説した前回に続いてlong doubleについて簡単に触れておきます。
第一回で触れたようにC規格におけるIEEE 754(IEC 60559)の浮動小数点数サポートはいまだAnnex扱い(Annex F:IEC 60559 floating-point arithmetic)であり、浮動小数点数にIEEE 754を使うことが必須ではありません。とはいえ、実態としては多くのメジャーな環境においてこのAnnex Fの規定を採用しています。
C23では、floatはIEC 60559のbinary32に、doubleは同binary64に適合することになっています。一方、long doubleはというと、同binary128に適合するか、そうでなければ同binary64-extended formatか、それでもなければ非IEC 60559のextended formatか、もしくはdoubleと同じbinary64に適合する、と書かれています。もちろんオプションなのでこれらは必須ではないです。
つまるところ、このオプションに従ってもなおlong doubleは様々な形式が許容されるのです。
実際、よくある環境でもlong doubleの形式は様々です。
たとえばここにmacが2台あるとします。一方はIntel mac、他方はApple Silicon(M1以降のArm系プロセッサ)を積んだマシンです。
それぞれの環境で以下のコードをビルドし実行してみます。
#include <stdio.h>
#include <float.h>
int main() {
printf("sizeof(long double): %zu bytes = %zu bits\n",
sizeof(long double), sizeof(long double) * 8);
printf("LDBL_MANT_DIG: %d\n", LDBL_MANT_DIG);
}
Intel mac
まずはIntel macです。
sizeof(long double): 16 bytes = 128 bits
LDBL_MANT_DIG: 64
LDBL_MANT_DIGはfloat.hに定義されたマクロで、long double型の仮数部(mantissa)の桁数を意味します。Intel macではLDBL_MANT_DIGが64と出力されました。これはAnnex Fにおける「binary64-extended format」のことです。実は、この「binary64-extended format」というものが曲者でして、ざっくりとdouble(つまりbinary64)を拡張した形式というだけで詳細な仕様が定められているわけではありません。とはいえ、歴史的にx86系のインテルマシンではx87(8087から始まる浮動小数点演算ユニット。486あたりからインテルプロセッサに統合)が対応する拡張倍精度(x86 extended-precision format)を使っていることから、世界的に見るとかなりの割合のPCで使われているbinary64-extended formatといえばx86 extended-precision formatになるでしょう、たぶん。
Apple Silicon mac
M3 macで試します。
sizeof(long double): 8 bytes = 64 bits
LDBL_MANT_DIG: 53
今度はビット幅が64ビットになっています。LDBL_MANT_DIGが53というのは暗黙の1を加えた桁数であり、つまりdouble型と同じということです。冒頭のAnnex Fの説明で述べた「もしくはdoubleと同じbinary64に適合する」というやつです。なんとApple SiliconはIntel macより退化しています。これは残念な仕様です。
余談ながら、Apple SiliconでもRosetta2のおかげでx86のバイナリを実行可能です。よって、以下のようにするとlong doubleが拡張倍精度になります。このためにというわけではないですけど、将来的にRosetta2廃止という方針やめてほしいです。
$ cc ldbl_check.c
$ ./a.out
sizeof(long double): 8 bytes = 64 bits
LDBL_MANT_DIG: 53
$ cc -arch x86_64 ldbl_check.c
$ ./a.out
sizeof(long double): 16 bytes = 128 bits
LDBL_MANT_DIG: 64
Linux on Apple Silicon mac
さらにApple Siliconのマシン上のUTMで動作しているLinux(Ubuntu)でも試してみると面白いです。
sizeof(long double): 16 bytes = 128 bits
LDBL_MANT_DIG: 113
今度は128ビット幅で、LDBL_MANT_DIGが113と表示されました。
これは4倍精度と呼ばれるものであり、より高い精度で幅広い数値をハンドル出来ます。macosでも対応して欲しいところです。
というわけで、つまりは同じApple Siliconのハードウェア上でも環境(条件)によりlong doubleが3つの異なる形式を取ります。printfの機能として実装するならば、ターゲット環境に応じた形式に対応するようなコードにすることが望ましいでしょう。
形式の違い
このようにメジャーな環境であっても3つのlong doubleがあり得るわけですが、80ビット拡張倍精度には注意が必要です。なぜならdoubleでは存在するケチ表現とも呼ばれる暗黙の1がここにはないからです。つまり、64ビットに整数部も含んでいます。
|符号部 1bit|指数部 15bit|仮数部 64bit| 合計80bit
128ビットとなる4倍精度はdouble同様にケチ表現を採用しています。というわけで、80ビット拡張倍精度についてのみ、この部分に関して配慮が必要ということになります。
|符号部 1bit|指数部 15bit|仮数部 112bit| 合計128bit
浮動小数点数のデータとしては80ビットも128ビットも通常は(特殊な処理をしなければ)16バイトのメモリ領域を占めます。インテル系プロセッサが80ビット拡張倍精度を採用しているのは歴史的経緯からですが、もういい加減4倍精度に移行出来ないものでしょうかね。
128ビットlong doubleの桁数
ところで4倍精度の場合にはどれだけの桁数が必要でしょうか? これは有効桁数とは別のものであり、あくまでprintf系としての出力桁数を意味しています。ちなみにこの話題を2025年時点のLLMに質問するとまず間違った回答を返してきます。正しくなるように誘導してもなかなか軌道修正されません。学習データがよろしくないのでしょう。そんなことを気にしている書き込みがネット上にそれほど存在していないということかもしれません。
桁数については計算により求められます。
最多になるのはたとえばLDBL_TRUN_MINのときです。
指数部
仮数部
小数点以下の桁数は
バッファを確保する際に「5000文字もあれば足りるでしょ」なんて適当なことを考えてはいけません。
当然、処理にはこれだけの桁数分の多倍長整数演算が必要となり、コストはそれなりに高くなります。
最後にprintf("%.16494Lf\n", LDBL_TRUE_MIN)
の出力結果を貼っております。見たくないかもしれませんが。
なお、次回は小数点表示の中でももっともマイナーと思われるa変換指定子について触れる予定です。
0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000647517511943802511092443895822764655249956933803468100968988438919703954012411937101767149127664994025587814147684811967658721988638254204668511007197261798304279271075133493441673462563847174023944852650555399039145555625217114806807082203468825698247627282878910302835733756134803106238656459263982622699190790786766326206571121158306465719606830833284523445306976052648944766096457931375140340263180435003994887007525564871336806611787940315576671330346743493706240941168521513760733313942284383505166898356716719680264295235350407971434710386053778289370021552116866771104295061002188151362798642946170043333920193539749882518433538551489284433993085296783844868212550230411412215304594646546308476411017447873704433531238966148363921055394341147654478626139787506419145122676761462589279036996141506960698000708050278864891997591680187822200225238172304723097187657099542882121928159654763302353878313718364639695283153055106868341959673537408674629052586799621690532336531988517260995682762551103633247835322894763188005068455915060831898652154013606127377149339041278475655210389751852776415877875933388071488227963332382639731237540692703944652530644783851437150365498785517230630758415545982670709590961775252680040132699082872163372677044091543909267790664679857352419911664826420692045116013363507136177381212171652817814824072078322673654962373613527499030913814318324837195987597880502750092869380807333695575275908844286560007519988899832388064354967005550542136243510857273208732298202718777245923122898947237295186432109926187878108433025298833392136299896330372243105974196876345240695383501512053377338528990471084362840270027470287047407382524882888998499428460760484721179422121072991315982901421716800446104953266269654291318362815719956164194992393662936899285662138308454532763697226554235534174985566302000488731683521615676722305379981106725891380846999423260785885452406443214577592214453570123646898570521297704547948951569000938892362558068578870760587734385766917089465679742336849032940725116039335604882060708508906902541358426981673974721123951355041438311750882676314351286200649705804114529609789291799993557705323425269869193379272475368218453768283556282993863000483838436394424313762286491825747425628012729111696505060017812047772078474218420537619597583167772176474004453662464576447138157145238183012539876515208328748311027939469785591571398193997068459919959486300723062407678613961755463145073499519008193218761681423463273877822443325646373834643527490571092558110606127384097559293176126679926558776546894676433708519236935831629845745000880942858692150474373087389571047461448000372714616234985833329151655216254537031220039084158830948097327463164627359739024947774665713189119648239867011879791009891889968948219695666063822573196069354276396430230899969295709106130018364832978518279330140726720004638304300523675997738760140776911038329572991865452093778558639063315702034763281210872863858981328256952957676936717332476408528570530831295495740155824716873993144656942281872348247109737436210527927855857074627816833159690379952795900167485615556461982140704479972002062064223324605784823647604754076284978832543563059242019449044353942899089948865589018388678865051859554218025793920053964504180838776023818956242835177463244062261805691313749982002192473317366803680648573344356703961386603717615595525382754847336044051704942269607550118329257306325061302116750385856108223837443919341323147260807288873332651285328780677338907329929737276024439735579150200465445811872803751032903412064303018234671601197499671959893427763529776295883724738936690976336749368229943036266899619393540522622118028046269135391228245570175981003711643996888363959610892641352882620050251155107166154107124189231907081299426951808638529599238102595717299239931214141421023554770700855559004950929404833117825888564525429573783492759033277310584382679775654003981029502169903778822820507214673809432026198082325209685287567059136619455659554947036209031723334912816047562629324653843003922646387725351785506298189005871241586657872769436287780507859411593904992269721568913904288447582979820139922184333984314433432975097626505437589863708761940677635786234159953958577217336256992972321731385621861073907991169392839557335410769520792438944304773598609705711710276164739858374670406622219248962849157924186151222845794272767765621706806030406343185944499909287309554680803589407119387267692420789359505133406787086697858524106329839944880166497950357625873085313776265671593267458487840876507434871535080821116048803756737008244959691404437863138435157451457440726626860151841812114063901777295075543982235214260546563975633093718543481277643745517005270425487368952598944565278155947464422753768496432162594620064734772610046887544579759229119236372464110060257172396010438972756148761621389388015869926156535386039426841251947825075588212150235085577754898735495718761136464434778346062391856979035771207870803007172986214720411906200314578305765796433562049068665477777585777241723065400566938013727218865010450285956328253564273453343056728731949830452891587663837029660720965472724681012074914701157984600768687687234897876761019701816744410153265650069958640767440432524938018706695622887762120628113014103533992925989508721680997635603930417632461505122386364213298749398928209613202371962867517965979309944112423418135458308263630611543033524825663659554275306357794617739929433631845961175483118965706507967993492812911329518941166074930622674706175331676048029076084642134755755360718525446251499163478916321559255456528862502142906459421744403443509463548980129463604421714189412860856020083794290110401471378303904658722883388803270951373270010166700283388501014240762023343810686108706205590687487289349113367848425972082088639772443893994432644994251669662868351003042623725776542626953259524818328961160237395230507382702942583848100744336148117203366419989361493262355437810131335392569916276758180944417495729353264103411236716394047249645482664549660826849143597533075479202247341325464163530913136536001391490951996323604695289708934701613673898413313379087410114316869102214191896779787747645010058506734876618322499081425361076359297473178426383285367504534324653325496613131153141106847871042978679181140465868080558810576851829209812925916415115312661534149837932435395345072387409240115201578762887939060378505752237508832277936400701843358254367309099083335229630229039016533664735524236598290367064856372723928354724120202902190199349345323140754394253337430312885554471885468113381870371730961599956361702606936020815639321492433385603772677125985793129848790900678298719592683591053727921358290566738493574587148388072495968537728445545132500938935911535634185974754830207571561443987671230411399567925090745488389530239663238165323053203269548175123194006285602445665638122071341343132544448375753426244933967514721424307914459865880820254892631212059669786335655472234811419496940917407245537222135482618988202392252487605493590592945425892550538789803952832907668955110893234285624369799963793822806866559534585597821542027455856236859023646771188477051266632830675628655934857463627291641433234999222527737907195209523444304182005485497032393140407761032373098891488918835612753391407485610708647983158473975562210683497136899733424643226401275726162895421362617779712728981835755892659191117537613455473736767294122441696659914452068803303238849446459748160068423317996968871337715396910701482058650018789002841975996662912589690385972448201855156736845933943728202747316371363055437014651828106804970184957508974343234930884928145618274502701184565362629078073829918130577248200125099176104754334479045462594315608504466110357651252336616135109964075113538514830591398788900869800923437094189134609830643793766122717238650698063690374354128523560578016721600892082861084206652209658950042094060640569266410990506323486611707751630869417570912321947628323029020749755515946714997934702020967350049665102355447500505399129537443072852477121243510738266431884270319781190107502703670304141931522915626327970886506400447339240171081753304021015275796669141647183636149854624918086604903973829426586386492540613575242853715988013206104282809077273310356143702107093883552048498756478490235782664500618538484729971151304255891311655067984298178573771372579004512809441167626485857320152907367807339638751926837379858254826386859211966609738118925524719064135219544308143294598190122371674571254374484714650301246008521614833580761962452839606901037087198164271275593296948450115518448745459784637578259880970809689364543985647863450814685906597817935100758074492897411452978821522648460182497414010735275877637899380000847946364045977378810603922164752791561963837589727965394686705736633783472126550008103569537295818707736763384842635134595953764413125539388694982804096611276801374567147662222197317229902132272383068434505481815748450176011373429966229824203945969448407467180888012626196399930140083357536658722023918044388594863491143267245490957847958697606459812663317783501182481204044009052973691543656433031778434326094141919900799456555633619565499476776839164184316729124258788240009120812434866999634307006102673255458742877997643951225916173703633584768234672853954977849338887052810296982292397645402247732207520490542037782380087654072456078224254004335849430575864839007138855614295499144089502603434229775462438747273269742326021101473172919613917251405395259142824788738324334475538910449603797536067722476559121197038221222594279759200527268078738623930394668942329370914896599940079590507375669702596756439666102748960633787215285415188757440097915087029597806677305991310314133809420614044615359578465969611699945126562704916274528149283184603386570790830494497573257463709010213075286024149615989772056652371147767391049237625724501965727173445141756593203484634107009301826277750779002612230277568017902572368523088345992463146260217553597800183627323574116428303466187123853728583196710745517517535358390707392142847337569520517907785592517088192226248043758847388926042386194109223749016069372127324062038676433519493108834897679875936743283578227831515029271833004625318824853722160041051755203800110174747880289060625994912044287612378359088556065625246018635790500914076191439918598667743937297559655094970714020006618496348625967305473951238868757826364413821456631254354535972707643378303742746504195366925683669474252273786690925881074373957950536867961073627490165000240704238728519647790865820451663465619716223395668776722264188162958730949161467232511411439104654922064720337142462986159828838334648766456731933873743225363023672070688260601987216708838704867314586153630901313495513111642228701713679240756375918406757485802550621390225930614926168099275260457933657233665059918500810800760783452520039166800267236031767353119811507595949084742214031774330195295184873141551680265791895758268696250195805872728809394511284458939711712334163519198881997064641182607001984672164146959109216402440139534348914796507058381160110567423665540425003738328954912183246033347861541003531213135973451967435783624650843915918907173834275229679522001174149998582071145513918745913557852095986167061022492545574120705909462524344111990614935124109843462972392381196792182169294313838491851529627642534803362969065499299101482595350676271526992105965363581364886771627097103730326454063985576045514371607042075088664819647092723929544772484111516471126427516674013320431128243647163056174914074487243575463379929857410388649441301822662353515625
Discussion