☰

11 Big Integers

\(\newcommand{\footnotename}{footnote}\) \(\def \LWRfootnote {1}\) \(\newcommand {\footnote }[2][\LWRfootnote ]{{}^{\mathrm {#1}}}\) \(\newcommand {\footnotemark }[1][\LWRfootnote ]{{}^{\mathrm {#1}}}\) \(\let \LWRorighspace \hspace \) \(\renewcommand {\hspace }{\ifstar \LWRorighspace \LWRorighspace }\) \(\newcommand {\TextOrMath }[2]{#2}\) \(\newcommand {\mathnormal }[1]{{#1}}\) \(\newcommand \ensuremath [1]{#1}\) \(\newcommand {\LWRframebox }[2][]{\fbox {#2}} \newcommand {\framebox }[1][]{\LWRframebox } \) \(\newcommand {\setlength }[2]{}\) \(\newcommand {\addtolength }[2]{}\) \(\newcommand {\setcounter }[2]{}\) \(\newcommand {\addtocounter }[2]{}\) \(\newcommand {\arabic }[1]{}\) \(\newcommand {\number }[1]{}\) \(\newcommand {\noalign }[1]{\text {#1}\notag \\}\) \(\newcommand {\cline }[1]{}\) \(\newcommand {\directlua }[1]{\text {(directlua)}}\) \(\newcommand {\luatexdirectlua }[1]{\text {(directlua)}}\) \(\newcommand {\protect }{}\) \(\def \LWRabsorbnumber #1 {}\) \(\def \LWRabsorbquotenumber "#1 {}\) \(\newcommand {\LWRabsorboption }[1][]{}\) \(\newcommand {\LWRabsorbtwooptions }[1][]{\LWRabsorboption }\) \(\def \mathchar {\ifnextchar "\LWRabsorbquotenumber \LWRabsorbnumber }\) \(\def \mathcode #1={\mathchar }\) \(\let \delcode \mathcode \) \(\let \delimiter \mathchar \) \(\def \oe {\unicode {x0153}}\) \(\def \OE {\unicode {x0152}}\) \(\def \ae {\unicode {x00E6}}\) \(\def \AE {\unicode {x00C6}}\) \(\def \aa {\unicode {x00E5}}\) \(\def \AA {\unicode {x00C5}}\) \(\def \o {\unicode {x00F8}}\) \(\def \O {\unicode {x00D8}}\) \(\def \l {\unicode {x0142}}\) \(\def \L {\unicode {x0141}}\) \(\def \ss {\unicode {x00DF}}\) \(\def \SS {\unicode {x1E9E}}\) \(\def \dag {\unicode {x2020}}\) \(\def \ddag {\unicode {x2021}}\) \(\def \P {\unicode {x00B6}}\) \(\def \copyright {\unicode {x00A9}}\) \(\def \pounds {\unicode {x00A3}}\) \(\let \LWRref \ref \) \(\renewcommand {\ref }{\ifstar \LWRref \LWRref }\) \( \newcommand {\multicolumn }[3]{#3}\) \(\require {textcomp}\) \(\newcommand {\intertext }[1]{\text {#1}\notag \\}\) \(\let \Hat \hat \) \(\let \Check \check \) \(\let \Tilde \tilde \) \(\let \Acute \acute \) \(\let \Grave \grave \) \(\let \Dot \dot \) \(\let \Ddot \ddot \) \(\let \Breve \breve \) \(\let \Bar \bar \) \(\let \Vec \vec \) \(\renewcommand {\vec }{\boldsymbol }\) \(\newcommand {\Edge }{\ensuremath {\,\textemdash \,}}\) \(\newcommand \Const [1]{\text {\textsf {#1}}}\) \(\DeclareMathOperator {\lerp }{lerp}\) \(\DeclareMathOperator {\bitlen }{bitlen}\) \(\DeclareMathOperator {\sign }{sign}\) \(\newcommand {\I }{\mathrm {i}}\) \(\newcommand \AND {\mathbin {\&}}\) \(\newcommand \OR {\mathbin {|}}\) \(\newcommand \XOR {\mathbin {{}^{\wedge }}}\) \(\newcommand \shl {\ll }\) \(\newcommand \shr {\ggg }\) \(\newcommand \asr {\gg }\) \(\newcommand \NOT {\ensuremath {\mathord {\sim }}}\) \(\newcommand {\isep }{\mathrel {{.}\,{.}}}\) \(\newcommand {\Id }[1]{\mathit {#1}}\) \(\newcommand {\const }[1]{\mathsf {#1}}\) \(\newcommand {\algorithmname }[1]{\text {\textsc {#1}}}\) \(\newcommand {\bits }[1]{\text {#1}}\) \(\newcommand {\hexa }[1]{\mathtt {0x#1}}\) \(\newcommand {\num }[1]{#1}\) \(\newcommand {\qed }{\quad \square }\) \(\newcommand {\idiv }[2]{\lfloor #1/#2\rfloor }\) \(\newcommand \attribdot {\ensuremath {\mkern 1.5mu.\mkern 1.5mu}}\) \(\newcommand \attribxr [2]{#1\attribdot \text {#2}}\) \(\newcommand \attribir [2]{\Id {#1}\attribdot \text {#2}}\) \(\newcommand \attribii [2]{\Id {#1}\attribdot \Id {#2}}\) \(\newcommand \textsc [1]{#1}\) \(\require {colortbl}\) \(\let \LWRorigcolumncolor \columncolor \) \(\renewcommand {\columncolor }[2][named]{\LWRorigcolumncolor [#1]{#2}\LWRabsorbtwooptions }\) \(\let \LWRorigrowcolor \rowcolor \) \(\renewcommand {\rowcolor }[2][named]{\LWRorigrowcolor [#1]{#2}\LWRabsorbtwooptions }\) \(\let \LWRorigcellcolor \cellcolor \) \(\renewcommand {\cellcolor }[2][named]{\LWRorigcellcolor [#1]{#2}\LWRabsorbtwooptions }\) \(\newcommand {\tcbset }[1]{}\) \(\newcommand {\tcbsetforeverylayer }[1]{}\) \(\newcommand {\tcbox }[2][]{\boxed {\text {#2}}}\) \(\newcommand {\tcboxfit }[2][]{\boxed {#2}}\) \(\newcommand {\tcblower }{}\) \(\newcommand {\tcbline }{}\) \(\newcommand {\tcbtitle }{}\) \(\newcommand {\tcbsubtitle [2][]{\mathrm {#2}}}\) \(\newcommand {\tcboxmath }[2][]{\boxed {#2}}\) \(\newcommand {\tcbhighmath }[2][]{\boxed {#2}}\) \(\newcommand {\toprule }[1][]{\hline }\) \(\let \midrule \toprule \) \(\let \bottomrule \toprule \) \(\def \LWRbooktabscmidruleparen (#1)#2{}\) \(\newcommand {\LWRbooktabscmidrulenoparen }[1]{}\) \(\newcommand {\cmidrule }[1][]{\ifnextchar (\LWRbooktabscmidruleparen \LWRbooktabscmidrulenoparen }\) \(\newcommand {\morecmidrules }{}\) \(\newcommand {\specialrule }[3]{\hline }\) \(\newcommand {\addlinespace }[1][]{}\) \(\newcommand {\LWRsubmultirow }[2][]{#2}\) \(\newcommand {\LWRmultirow }[2][]{\LWRsubmultirow }\) \(\newcommand {\multirow }[2][]{\LWRmultirow }\) \(\newcommand {\mrowcell }{}\) \(\newcommand {\mcolrowcell }{}\) \(\newcommand {\STneed }[1]{}\) \(\newcommand {\LWRldelimtwo }[1][]{\text {#1}~\LWRbigdelim }\) \(\newcommand {\LWRldelimone }[2][]{\LWRldelimtwo }\) \(\def \ldelim #1#2{\def \LWRbigdelim {#1}\LWRldelimone }\) \(\newcommand {\LWRrdelimtwo }[1][]{\LWRbigdelim ~\text {#1}}\) \(\newcommand {\LWRrdelimone }[2][]{\LWRrdelimtwo }\) \(\def \rdelim #1#2{\def \LWRbigdelim {#1}\LWRrdelimone }\) \(\let \symnormal \mathit \) \(\let \symliteral \mathrm \) \(\let \symbb \mathbb \) \(\let \symbbit \mathbb \) \(\let \symcal \mathcal \) \(\let \symscr \mathscr \) \(\let \symfrak \mathfrak \) \(\let \symsfup \mathsf \) \(\let \symsfit \mathit \) \(\let \symbfsf \mathbf \) \(\let \symbfup \mathbf \) \(\newcommand {\symbfit }[1]{\boldsymbol {#1}}\) \(\let \symbfcal \mathcal \) \(\let \symbfscr \mathscr \) \(\let \symbffrak \mathfrak \) \(\let \symbfsfup \mathbf \) \(\newcommand {\symbfsfit }[1]{\boldsymbol {#1}}\) \(\let \symup \mathrm \) \(\let \symbf \mathbf \) \(\let \symit \mathit \) \(\let \symsf \symsfit \) \(\let \symtt \mathtt \) \(\let \symbffrac \mathbffrac \) \(\newcommand {\mathfence }[1]{\mathord {#1}}\) \(\newcommand {\mathover }[1]{#1}\) \(\newcommand {\mathunder }[1]{#1}\) \(\newcommand {\mathaccent }[1]{#1}\) \(\newcommand {\mathbotaccent }[1]{#1}\) \(\newcommand {\mathalpha }[1]{\mathord {#1}}\) \(\def\Alpha{\unicode{x1D6E2}}\) \(\def\Beta{\unicode{x1D6E3}}\) \(\def\Gamma{\unicode{x1D6E4}}\) \(\def\Digamma{\mathit{\unicode{x03DC}}}\) \(\def\Delta{\unicode{x1D6E5}}\) \(\def\Epsilon{\unicode{x1D6E6}}\) \(\def\Zeta{\unicode{x1D6E7}}\) \(\def\Eta{\unicode{x1D6E8}}\) \(\def\Theta{\unicode{x1D6E9}}\) \(\def\Vartheta{\unicode{x1D6F3}}\) \(\def\Iota{\unicode{x1D6EA}}\) \(\def\Kappa{\unicode{x1D6EB}}\) \(\def\Lambda{\unicode{x1D6EC}}\) \(\def\Mu{\unicode{x1D6ED}}\) \(\def\Nu{\unicode{x1D6EE}}\) \(\def\Xi{\unicode{x1D6EF}}\) \(\def\Omicron{\unicode{x1D6F0}}\) \(\def\Pi{\unicode{x1D6F1}}\) \(\def\Rho{\unicode{x1D6F2}}\) \(\def\Sigma{\unicode{x1D6F4}}\) \(\def\Tau{\unicode{x1D6F5}}\) \(\def\Upsilon{\unicode{x1D6F6}}\) \(\def\Phi{\unicode{x1D6F7}}\) \(\def\Chi{\unicode{x1D6F8}}\) \(\def\Psi{\unicode{x1D6F9}}\) \(\def\Omega{\unicode{x1D6FA}}\) \(\def\alpha{\unicode{x1D6FC}}\) \(\def\beta{\unicode{x1D6FD}}\) \(\def\varbeta{\unicode{x03D0}}\) \(\def\gamma{\unicode{x1D6FE}}\) \(\def\digamma{\mathit{\unicode{x03DD}}}\) \(\def\delta{\unicode{x1D6FF}}\) \(\def\epsilon{\unicode{x1D716}}\) \(\def\varepsilon{\unicode{x1D700}}\) \(\def\zeta{\unicode{x1D701}}\) \(\def\eta{\unicode{x1D702}}\) \(\def\theta{\unicode{x1D703}}\) \(\def\vartheta{\unicode{x1D717}}\) \(\def\iota{\unicode{x1D704}}\) \(\def\kappa{\unicode{x1D705}}\) \(\def\varkappa{\unicode{x1D718}}\) \(\def\lambda{\unicode{x1D706}}\) \(\def\mu{\unicode{x1D707}}\) \(\def\nu{\unicode{x1D708}}\) \(\def\xi{\unicode{x1D709}}\) \(\def\omicron{\unicode{x1D70A}}\) \(\def\pi{\unicode{x1D70B}}\) \(\def\varpi{\unicode{x1D71B}}\) \(\def\rho{\unicode{x1D70C}}\) \(\def\varrho{\unicode{x1D71A}}\) \(\def\sigma{\unicode{x1D70E}}\) \(\def\varsigma{\unicode{x1D70D}}\) \(\def\tau{\unicode{x1D70F}}\) \(\def\upsilon{\unicode{x1D710}}\) \(\def\phi{\unicode{x1D719}}\) \(\def\varphi{\unicode{x1D711}}\) \(\def\chi{\unicode{x1D712}}\) \(\def\psi{\unicode{x1D713}}\) \(\def\omega{\unicode{x1D714}}\) \(\def\upAlpha{\unicode{x0391}}\) \(\def\upBeta{\unicode{x0392}}\) \(\def\upGamma{\unicode{x0393}}\) \(\def\upDigamma{\unicode{x03DC}}\) \(\def\upDelta{\unicode{x0394}}\) \(\def\upEpsilon{\unicode{x0395}}\) \(\def\upZeta{\unicode{x0396}}\) \(\def\upEta{\unicode{x0397}}\) \(\def\upTheta{\unicode{x0398}}\) \(\def\upVartheta{\unicode{x03F4}}\) \(\def\upIota{\unicode{x0399}}\) \(\def\upKappa{\unicode{x039A}}\) \(\def\upLambda{\unicode{x039B}}\) \(\def\upMu{\unicode{x039C}}\) \(\def\upNu{\unicode{x039D}}\) \(\def\upXi{\unicode{x039E}}\) \(\def\upOmicron{\unicode{x039F}}\) \(\def\upPi{\unicode{x03A0}}\) \(\def\upVarpi{\unicode{x03D6}}\) \(\def\upRho{\unicode{x03A1}}\) \(\def\upSigma{\unicode{x03A3}}\) \(\def\upTau{\unicode{x03A4}}\) \(\def\upUpsilon{\unicode{x03A5}}\) \(\def\upPhi{\unicode{x03A6}}\) \(\def\upChi{\unicode{x03A7}}\) \(\def\upPsi{\unicode{x03A8}}\) \(\def\upOmega{\unicode{x03A9}}\) \(\def\itAlpha{\unicode{x1D6E2}}\) \(\def\itBeta{\unicode{x1D6E3}}\) \(\def\itGamma{\unicode{x1D6E4}}\) \(\def\itDigamma{\mathit{\unicode{x03DC}}}\) \(\def\itDelta{\unicode{x1D6E5}}\) \(\def\itEpsilon{\unicode{x1D6E6}}\) \(\def\itZeta{\unicode{x1D6E7}}\) \(\def\itEta{\unicode{x1D6E8}}\) \(\def\itTheta{\unicode{x1D6E9}}\) \(\def\itVartheta{\unicode{x1D6F3}}\) \(\def\itIota{\unicode{x1D6EA}}\) \(\def\itKappa{\unicode{x1D6EB}}\) \(\def\itLambda{\unicode{x1D6EC}}\) \(\def\itMu{\unicode{x1D6ED}}\) \(\def\itNu{\unicode{x1D6EE}}\) \(\def\itXi{\unicode{x1D6EF}}\) \(\def\itOmicron{\unicode{x1D6F0}}\) \(\def\itPi{\unicode{x1D6F1}}\) \(\def\itRho{\unicode{x1D6F2}}\) \(\def\itSigma{\unicode{x1D6F4}}\) \(\def\itTau{\unicode{x1D6F5}}\) \(\def\itUpsilon{\unicode{x1D6F6}}\) \(\def\itPhi{\unicode{x1D6F7}}\) \(\def\itChi{\unicode{x1D6F8}}\) \(\def\itPsi{\unicode{x1D6F9}}\) \(\def\itOmega{\unicode{x1D6FA}}\) \(\def\upalpha{\unicode{x03B1}}\) \(\def\upbeta{\unicode{x03B2}}\) \(\def\upvarbeta{\unicode{x03D0}}\) \(\def\upgamma{\unicode{x03B3}}\) \(\def\updigamma{\unicode{x03DD}}\) \(\def\updelta{\unicode{x03B4}}\) \(\def\upepsilon{\unicode{x03F5}}\) \(\def\upvarepsilon{\unicode{x03B5}}\) \(\def\upzeta{\unicode{x03B6}}\) \(\def\upeta{\unicode{x03B7}}\) \(\def\uptheta{\unicode{x03B8}}\) \(\def\upvartheta{\unicode{x03D1}}\) \(\def\upiota{\unicode{x03B9}}\) \(\def\upkappa{\unicode{x03BA}}\) \(\def\upvarkappa{\unicode{x03F0}}\) \(\def\uplambda{\unicode{x03BB}}\) \(\def\upmu{\unicode{x03BC}}\) \(\def\upnu{\unicode{x03BD}}\) \(\def\upxi{\unicode{x03BE}}\) \(\def\upomicron{\unicode{x03BF}}\) \(\def\uppi{\unicode{x03C0}}\) \(\def\upvarpi{\unicode{x03D6}}\) \(\def\uprho{\unicode{x03C1}}\) \(\def\upvarrho{\unicode{x03F1}}\) \(\def\upsigma{\unicode{x03C3}}\) \(\def\upvarsigma{\unicode{x03C2}}\) \(\def\uptau{\unicode{x03C4}}\) \(\def\upupsilon{\unicode{x03C5}}\) \(\def\upphi{\unicode{x03D5}}\) \(\def\upvarphi{\unicode{x03C6}}\) \(\def\upchi{\unicode{x03C7}}\) \(\def\uppsi{\unicode{x03C8}}\) \(\def\upomega{\unicode{x03C9}}\) \(\def\italpha{\unicode{x1D6FC}}\) \(\def\itbeta{\unicode{x1D6FD}}\) \(\def\itvarbeta{\unicode{x03D0}}\) \(\def\itgamma{\unicode{x1D6FE}}\) \(\def\itdigamma{\mathit{\unicode{x03DD}}}\) \(\def\itdelta{\unicode{x1D6FF}}\) \(\def\itepsilon{\unicode{x1D716}}\) \(\def\itvarepsilon{\unicode{x1D700}}\) \(\def\itzeta{\unicode{x1D701}}\) \(\def\iteta{\unicode{x1D702}}\) \(\def\ittheta{\unicode{x1D703}}\) \(\def\itvartheta{\unicode{x1D717}}\) \(\def\itiota{\unicode{x1D704}}\) \(\def\itkappa{\unicode{x1D705}}\) \(\def\itvarkappa{\unicode{x1D718}}\) \(\def\itlambda{\unicode{x1D706}}\) \(\def\itmu{\unicode{x1D707}}\) \(\def\itnu{\unicode{x1D708}}\) \(\def\itxi{\unicode{x1D709}}\) \(\def\itomicron{\unicode{x1D70A}}\) \(\def\itpi{\unicode{x1D70B}}\) \(\def\itvarpi{\unicode{x1D71B}}\) \(\def\itrho{\unicode{x1D70C}}\) \(\def\itvarrho{\unicode{x1D71A}}\) \(\def\itsigma{\unicode{x1D70E}}\) \(\def\itvarsigma{\unicode{x1D70D}}\) \(\def\ittau{\unicode{x1D70F}}\) \(\def\itupsilon{\unicode{x1D710}}\) \(\def\itphi{\unicode{x1D719}}\) \(\def\itvarphi{\unicode{x1D711}}\) \(\def\itchi{\unicode{x1D712}}\) \(\def\itpsi{\unicode{x1D713}}\) \(\def\itomega{\unicode{x1D714}}\) \(\let \lparen (\) \(\let \rparen )\) \(\newcommand {\cuberoot }[1]{\,{}^3\!\!\sqrt {#1}}\,\) \(\newcommand {\fourthroot }[1]{\,{}^4\!\!\sqrt {#1}}\,\) \(\newcommand {\longdivision }[1]{\mathord {\unicode {x027CC}#1}}\) \(\newcommand {\mathcomma }{,}\) \(\newcommand {\mathcolon }{:}\) \(\newcommand {\mathsemicolon }{;}\) \(\newcommand {\overbracket }[1]{\mathinner {\overline {\ulcorner {#1}\urcorner }}}\) \(\newcommand {\underbracket }[1]{\mathinner {\underline {\llcorner {#1}\lrcorner }}}\) \(\newcommand {\overbar }[1]{\mathord {#1\unicode {x00305}}}\) \(\newcommand {\ovhook }[1]{\mathord {#1\unicode {x00309}}}\) \(\newcommand {\ocirc }[1]{\mathord {#1\unicode {x0030A}}}\) \(\newcommand {\candra }[1]{\mathord {#1\unicode {x00310}}}\) \(\newcommand {\oturnedcomma }[1]{\mathord {#1\unicode {x00312}}}\) \(\newcommand {\ocommatopright }[1]{\mathord {#1\unicode {x00315}}}\) \(\newcommand {\droang }[1]{\mathord {#1\unicode {x0031A}}}\) \(\newcommand {\leftharpoonaccent }[1]{\mathord {#1\unicode {x020D0}}}\) \(\newcommand {\rightharpoonaccent }[1]{\mathord {#1\unicode {x020D1}}}\) \(\newcommand {\vertoverlay }[1]{\mathord {#1\unicode {x020D2}}}\) \(\newcommand {\leftarrowaccent }[1]{\mathord {#1\unicode {x020D0}}}\) \(\newcommand {\annuity }[1]{\mathord {#1\unicode {x020E7}}}\) \(\newcommand {\widebridgeabove }[1]{\mathord {#1\unicode {x020E9}}}\) \(\newcommand {\asteraccent }[1]{\mathord {#1\unicode {x020F0}}}\) \(\newcommand {\threeunderdot }[1]{\mathord {#1\unicode {x020E8}}}\) \(\newcommand {\Bbbsum }{\mathop {\unicode {x2140}}\limits }\) \(\newcommand {\oiint }{\mathop {\unicode {x222F}}\limits }\) \(\newcommand {\oiiint }{\mathop {\unicode {x2230}}\limits }\) \(\newcommand {\intclockwise }{\mathop {\unicode {x2231}}\limits }\) \(\newcommand {\ointclockwise }{\mathop {\unicode {x2232}}\limits }\) \(\newcommand {\ointctrclockwise }{\mathop {\unicode {x2233}}\limits }\) \(\newcommand {\varointclockwise }{\mathop {\unicode {x2232}}\limits }\) \(\newcommand {\leftouterjoin }{\mathop {\unicode {x27D5}}\limits }\) \(\newcommand {\rightouterjoin }{\mathop {\unicode {x27D6}}\limits }\) \(\newcommand {\fullouterjoin }{\mathop {\unicode {x27D7}}\limits }\) \(\newcommand {\bigbot }{\mathop {\unicode {x27D8}}\limits }\) \(\newcommand {\bigtop }{\mathop {\unicode {x27D9}}\limits }\) \(\newcommand {\xsol }{\mathop {\unicode {x29F8}}\limits }\) \(\newcommand {\xbsol }{\mathop {\unicode {x29F9}}\limits }\) \(\newcommand {\bigcupdot }{\mathop {\unicode {x2A03}}\limits }\) \(\newcommand {\bigsqcap }{\mathop {\unicode {x2A05}}\limits }\) \(\newcommand {\conjquant }{\mathop {\unicode {x2A07}}\limits }\) \(\newcommand {\disjquant }{\mathop {\unicode {x2A08}}\limits }\) \(\newcommand {\bigtimes }{\mathop {\unicode {x2A09}}\limits }\) \(\newcommand {\modtwosum }{\mathop {\unicode {x2A0A}}\limits }\) \(\newcommand {\sumint }{\mathop {\unicode {x2A0B}}\limits }\) \(\newcommand {\intbar }{\mathop {\unicode {x2A0D}}\limits }\) \(\newcommand {\intBar }{\mathop {\unicode {x2A0E}}\limits }\) \(\newcommand {\fint }{\mathop {\unicode {x2A0F}}\limits }\) \(\newcommand {\cirfnint }{\mathop {\unicode {x2A10}}\limits }\) \(\newcommand {\awint }{\mathop {\unicode {x2A11}}\limits }\) \(\newcommand {\rppolint }{\mathop {\unicode {x2A12}}\limits }\) \(\newcommand {\scpolint }{\mathop {\unicode {x2A13}}\limits }\) \(\newcommand {\npolint }{\mathop {\unicode {x2A14}}\limits }\) \(\newcommand {\pointint }{\mathop {\unicode {x2A15}}\limits }\) \(\newcommand {\sqint }{\mathop {\unicode {x2A16}}\limits }\) \(\newcommand {\intlarhk }{\mathop {\unicode {x2A17}}\limits }\) \(\newcommand {\intx }{\mathop {\unicode {x2A18}}\limits }\) \(\newcommand {\intcap }{\mathop {\unicode {x2A19}}\limits }\) \(\newcommand {\intcup }{\mathop {\unicode {x2A1A}}\limits }\) \(\newcommand {\upint }{\mathop {\unicode {x2A1B}}\limits }\) \(\newcommand {\lowint }{\mathop {\unicode {x2A1C}}\limits }\) \(\newcommand {\bigtriangleleft }{\mathop {\unicode {x2A1E}}\limits }\) \(\newcommand {\zcmp }{\mathop {\unicode {x2A1F}}\limits }\) \(\newcommand {\zpipe }{\mathop {\unicode {x2A20}}\limits }\) \(\newcommand {\zproject }{\mathop {\unicode {x2A21}}\limits }\) \(\newcommand {\biginterleave }{\mathop {\unicode {x2AFC}}\limits }\) \(\newcommand {\bigtalloblong }{\mathop {\unicode {x2AFF}}\limits }\) \(\newcommand {\arabicmaj }{\mathop {\unicode {x1EEF0}}\limits }\) \(\newcommand {\arabichad }{\mathop {\unicode {x1EEF1}}\limits }\)

11.8 The Sign-Magnitude Representation

Now that we know how to represent and compute with nonnegative big integers, let’s generalize these ideas to arbitrary signed integers. We first note that every integer \(n\) can be written as the product of its sign and its magnitude[magnitude of an integer]:

\begin{equation} \label {eq:sign-magnitude} n = \sign {n}\cdot |n|. \end{equation}

By convention, \(\sign {n}\) is either \(-1\), \(+1\), or 0, depending on whether \(n\) is negative, positive, or zero. Splitting integers in this way is called sign-magnitude representation. This is the representation we will use for our implementation of signed big integers. The outline of the corresponding class BigInt is shown in Listing 11.20. We store the sign in a regular int and the magnitude in an instance of BigNat. The BigInt class is again immutable.

Listing 11.20ch11β€―/β€―BigInt

// Represents a signed big integer.
public final class BigInt implements Comparable<BigInt> {
    private final int sign;  // sign: -1, 0, 1
    private final BigNat magnitude;

    // Internal constructor from sign and magnitude.
    BigInt(int sign, BigNat magnitude) {
        this.sign = magnitude.equals(BigNat.ZERO) ? 0 : sign;
        this.magnitude = magnitude;
    }

    // ...
}

The internal constructor BigInt() creates a big integer from a sign and a magnitude. Before initializing the sign and magnitude fields, the constructor performs a simple normalization step to ensure the number zero doesn’t have a nonzero sign. From a mathematical perspective, this normalization isn’t strictly necessary, but it ensures that two BigInts with the same value also have the same internal representation.

Because magnitude cannot be modified, we can safely share its value between different instances of BigInt. This allows us to negate BigInts and compute their absolute value at almost no cost, simply by modifying the sign and reusing the existing magnitude; this gives us the signum(), negate(), and abs() methods shown in Listing 11.21.

Listing 11.21ch11β€―/β€―BigInt

public int signum() {return sign;}

public BigInt negate() {
    return new BigInt(-sign, magnitude);
}

public BigInt abs() {
    return new BigInt(+1, magnitude);
}

Listing 11.22 shows the implementations of equals() and hashCode(). Two BigInts are equal if their sign and magnitude fields are equal, and their hash codes can be computed by combining the hash codes of sign and magnitude. Notice that this only works if the constructor normalizes the sign as described above: If it were possible to combine a zero magnitude with a nonzero sign, both methods would need to be changed accordingly.

Listing 11.22ch11β€―/β€―BigInt

public boolean equals(Object o) {
    return (o instanceof BigInt b)
            && sign == b.sign && magnitude.equals(b.magnitude);
}

public int hashCode() {
    return Objects.hash(sign, magnitude);
}

Conversion to and from long integers is slightly more complicated than in the case of BigNat since we have to take the possibility of integer overflow into account. Let’s start with the problem of constructing an instance of BigInt from a value of type long. Listing 11.23 shows a possible implementation of a method valueOf() that performs this conversion. The listing also defines a few commonly used integer constants.

Listing 11.23ch11β€―/β€―BigInt

public static BigInt valueOf(long v) {
    if (v == Long.MIN_VALUE) {
        return new BigInt(-1, BigNat.fromUnsignedLong(1L << 63));
    } else {
        return new BigInt(Long.signum(v),
                BigNat.fromUnsignedLong(Math.abs(v)));
    }
}

public static final BigInt
        ZERO = valueOf(0),
        ONE = valueOf(1),
        TEN = valueOf(10);

This implementation of valueOf() handles MIN_VALUE as a special case because for this particular value Math.abs(v) overflows and returns a negative result. This is due to a property of two’s-complement representation we mentioned in Section 5.2: the smallest negative number has a greater magnitude than the largest positive number (\(-2^{63}\) vs. \(2^{63}-1\) in the case of 64-bit integers). Therefore, any computation that changes the sign of \(-2^{63}\) — whether by negating it, multiplying it by \(-1\), or computing its absolute value — produces a result that is most likely incorrect. (In this particular example, the code happens to work correctly even if we don’t handle the special case explicitly; we will discuss this in detail below.)

If we want to perform the opposite conversion, from big integers to long integers, we have to take into account that that numbers smaller than Long.MIN_VALUE or larger than Long.MAX_VALUE cannot be stored in the target type. For the similar toUnsignedLong() method in BigNat, we didn’t perform any range checks and simply returned the lowest 64 bits of the big integer. But this time, we would prefer a safer conversion operation that raises an exception if the number cannot be converted to long.

The toLong() method shown in Listing 11.24 performs this kind of safety check before converting a BigInt to long. If the current value is smaller than longMin or larger than longMax it stops and throws an exception. For most other values the function computes the result by multiplying the sign and the lowest 63 bits of the magnitude. To avoid integer overflow, the smallest allowed value Long.MIN_VALUE is again handled explicitly.

Listing 11.24ch11β€―/β€―BigInt

private static final BigInt
        longMin = valueOf(Long.MIN_VALUE),
        longMax = valueOf(Long.MAX_VALUE);

// Convert to 64-bit integer.
public long toLong() {
    if (compareTo(longMin) < 0 || compareTo(longMax) > 0)
        throw new ArithmeticException("Integer overflow");
    if (compareTo(longMin) == 0)
        return Long.MIN_VALUE;
    return sign * magnitude.toUnsignedLong();
}

Integer overflow is almost always an error that must prevented before it happens. But in rare circumstances, programs can produce the correct result even if integer overflow occurs in one of the intermediate steps.

The reason is that the result of overflow in two’s-complement arithmetic is always well-defined, even if it’s incorrect or unexpected. When working with signed integers of type int or long, all arithmetic operations are defined to wrap around at either end of the numeric range. For example, incrementing Long.MAX_VALUE by 1 produces a value that doesn’t fit into an long, so the computation wraps around to the other end of the numeric range and produces MIN_VALUE. Similarly, decrementing MIN_VALUE by 1 wraps around in the opposite direction and brings us back to MAX_VALUE. For this reason, the result of the integer expression

(x + 1) - 1

is always x, even if the addition or the subtraction overflows.

Something similar happens when negating the smallest integer MIN_VALUE, which has the value \(-2^{63}\). The correct result \(2^{63}\) is too large for a long integer, so the computation wraps around and produces \(-2^{63}\) again. In two’s-complement representation, we have the paradoxical result that

-MIN_VALUE == MIN_VALUE

In other words, the absolute value of the smallest negative integer MIN_VALUE is MIN_VALUE itself. This is true for any bit width.

We can use these observations to get rid of the special handling of MIN_VALUE in the implementations of BigInt. valueOf() and BigInt.toLong(). The simplified code becomes

public static BigInt valueOf(long v) {
   return new BigInt(Long.signum(v),
                     BigNat.fromBits(Math.abs(v)));
}

and

public long toLong() {
    if (compareTo(longMin) < 0 || compareTo(longMax) > 0)
        throw new ArithmeticException("Integer overflow");
    return sign * magnitude.toUnsignedLong();
}

To see that these implementations are correct, we have to verify that they compute the correct result when converting from or to MIN_VALUE. In the case of valueOf(), this is easy to verify. Since Math.abs() wraps around as described above, the expression

BigNat.fromBits(Math.abs(Long.MIN_VALUE))

is equivalent to

BigNat.fromBits(Long.MIN_VALUE)

The bit pattern of MIN_VALUE is 0x7000000000000000, which is also the bit pattern of the unsigned integer \(2^{63}\), so valueOf() returns \(-2^{63}\) as required.

In the implementation of toLong() we have the reverse situation. For a BigInt with value \(-2^{63}\), the expression

sign * magnitude.toUnsignedLong()

evaluates to

-1 * Long.MIN_VALUE

The multiplication overflows as described above and produces MIN_VALUE, which again happens to be the correct result.

Signed Arithmetic

Last but not least, let’s discuss how basic arithmetic works in the sign-magnitude representation. Suppose we want to add two signed integers \(x\) and \(y\). If the two numbers have the same sign, their sum \(x+y\) has that sign as well and its magnitude is \(|x|+|y|\). If the two numbers have opposite signs, however, the sign of \(x+y\) is the sign of the number with the larger absolute value, and we have to subtract the smaller magnitude from the larger one. We can therefore add two BigInts as demonstrated by the plus() method in Listing 11.25. If this and y have the same sign, we simply add their magnitudes. Otherwise, we determine one with the larger magnitude using compareTo() and subtract the smaller from the larger one. The return statement at the end of the method handles the special case cmp == 0, which occurs when adding a number to its negation. To compute the difference of two BigInts, we simply rewrite \(x-y\) as \(x+(-y)\) and reuse the implementation of plus().

Listing 11.25ch11β€―/β€―BigInt

// Compute the sum of two big integers.
public BigInt plus(BigInt y) {
    if (sign == y.sign)
        return new BigInt(sign, magnitude.plus(y.magnitude));
    int cmp = magnitude.compareTo(y.magnitude);
    if (cmp > 0)
        return new BigInt(sign, magnitude.minus(y.magnitude));
    if (cmp < 0)
        return new BigInt(y.sign, y.magnitude.minus(magnitude));
    return ZERO;
}

// Compute the difference of two big integers.
public BigInt minus(BigInt y) {
    return plus(y.negate());
}

Multiplying two signed integers \(x\) and \(y\) is easier than adding or subtracting them since both the sign and the magnitude of the product \(x\cdot y\) are obtained by multiplying the signs and magnitudes of the two operands separately:

\begin{align*} \sign (x\cdot y) = \sign x\cdot \sign y,\qquad |x\cdot y| = |x|\cdot |y|. \end{align*} The identities hold for all combinations of signs and magnitudes, in particular for cases where the sign (and the magnitude) are zero.

A similar relationship holds when dividing two signed integers: The sign of the quotient \(\idiv {x}{y}\) is again the product of the individual signs of \(x\) and \(y\), and the magnitude of the quotient is the quotient of the magnitudes:

\begin{align*} \sign \idiv {x}{y} &= \sign x\cdot \sign y,\\ \bigl |\idiv {x}{y}\bigr | &= \bigl \lfloor |x| / |y|\bigr \rfloor . \end{align*} To find the corresponding relationships for the remainders, its easiest to start with the definition

\begin{equation*} x\bmod y = x - \idiv {x}{y}\cdot y \end{equation*}

and infer the influence of the signs of \(x\) and \(y\) from a concrete example. If \(x=\pm 17\) and \(y=\pm 3\), we obtain the following table for the possible quotients and remainders:

\begin{equation*} \begin{array}{r|r|r|r} x & y & \idiv {x}{y} & x\bmod y\\ \hline 17 & 3 & 5 & 2\\ 17 & -3 & -5 & 2\\ -17 & 3 & -5 & -2\\ -17 & -3 & 5 & -2\\ \end {array} \end{equation*}

The sign of the remainder is therefore equal to the sign of \(x\) and its magnitude is just the remainder of \(|x|\) divided by \(|y|\):

\begin{align*} \sign (x\bmod y) &= \sign x,\\ |x\bmod y| &= |x| \bmod |y|. \end{align*} Listing 11.26 shows the code for multiplying and dividing two BigInts.

Listing 11.26ch11β€―/β€―BigInt

public BigInt times(BigInt y) {
    return new BigInt(sign * y.sign,
            magnitude.times(y.magnitude));
}

public BigInt[] divideAndRemainder(BigInt y) {
    var divRem = magnitude.divideAndRemainder(y.magnitude);
    return new BigInt[]{
            new BigInt(sign * y.sign, divRem[0]),
            new BigInt(sign, divRem[1])};
}

public BigInt dividedBy(BigInt y) {
    return divideAndRemainder(y)[0];
}

public BigInt remainder(BigInt y) {
    return divideAndRemainder(y)[1];
}
Exercises

Exercise 11.16.Implement a method compareTo() that performs a three-way comparison of two BigInts.