适合 A4 宽度的 IEEE-754 表

适合 A4 宽度的 IEEE-754 表

肯定问过一千遍了。我找到了很多答案,但似乎都没有用。我试过使用 tabular 和 tabularx,但不行。

\documentclass[12pt,a4paper]{article}

\usepackage{ucs}
\usepackage[utf8x]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{amsmath,amssymb,amstext,fancyhdr}
\usepackage{tabularx}
\pagestyle{fancy}

\rhead{1608/1609 WS18/19}

\begin{document}
\section*{Computersysteme II (01609) WS2018/19 EA 1}
\label{sec:Einsendeaufgabe 1}
\subsection*{Aufgabe 1 - Allgemeine Fragen}
...
\pagebreak
\subsection*{Aufgabe 3 - Gleitkommadarstellung}
Gegeben sei die Dezimalzahl $Z_{10}=-208,40625$.
\begin{itemize}
\item[a)] So richtig verstanden habe ich das Schema nicht...\\
 $Z_{32}=\left(-1\right)^1\cdot2^{135}\cdot\left(100001100,0110100\ldots\right)$
\item[b)] \begin{tabular}{|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|}
% {|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|}
% {|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|}
31 & 30 & 29 & 28 & 27 & 26 & 25 & 24 & 23 & 22 & 21 & 20 & 19 & 18 & 17 & 16 & 15 & 14 & 13 & 12 & 11 & 10 & 9 & 8 & 7 & 6 & 5 & 4 & 3 & 2 & 1 & 0\\
\hline
S & E & E & E & E & E & E & E & E & M & M & M & M & M & M & M & M & M & M & M & M & M & M & M & M\\
\hline
1 & 1 & 0 & 0 & 0 & 0 & 1 & 1 & 1 & 0 & 0 & 0 & 0 & 1 & 1 & 0 & 0 & 0 & 1 & 1 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0
\end{tabular}
\end{itemize}
\end{document}

当我在 {tabular} 后添加 {0.3\textwidth} 时,它会抱怨数字,并且只缩放 \hline。一些解决方案建议使用 \begin{table}。这也不起作用,并将表格移到了标题上方...

问候,Stephan

答案1

如果不采用更宽的线长则不行。

\documentclass[12pt,a4paper]{article}
\usepackage[left=2.5cm,right=2.5cm,headheight=14.5pt]{geometry}

\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[ngerman]{babel}

\usepackage{amsmath,amssymb,fancyhdr,array}

\pagestyle{fancy}

\rhead{1608/1609 WS18/19}

\begin{document}

\section*{Computersysteme II (01609) WS2018/19 EA 1}
\label{sec:Einsendeaufgabe 1}

\subsection*{Aufgabe 3 - Gleitkommadarstellung}

Gegeben sei die Dezimalzahl $Z_{10}=-208,40625$.
\begin{itemize}
\item[a)] So richtig verstanden habe ich das Schema nicht...\\
 $Z_{32}=\left(-1\right)^1\cdot2^{135}\cdot\left(100001100,0110100\ldots\right)$
\item[b)] 
{\footnotesize\setlength{\tabcolsep}{1pt}\begin{tabular}[t]{|*{32}{w{c}{1em}|}}
\firsthline
31 & 30 & 29 & 28 & 27 & 26 & 25 & 24 & 23 & 22 & 21 & 20 & 19 & 18 & 17 & 16 & 15 & 14 & 13 & 12 & 11 & 10 & 9 & 8 & 7 & 6 & 5 & 4 & 3 & 2 & 1 & 0\\
\hline
S & E & E & E & E & E & E & E & E & M & M & M & M & M & M & M & M & M & M & M & M & M & M & M & M\\
\hline
1 & 1 & 0 & 0 & 0 & 0 & 1 & 1 & 1 & 0 & 0 & 0 & 0 & 1 & 1 & 0 & 0 & 0 & 1 & 1 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\
\hline
\end{tabular}}

\end{itemize}

\end{document}

不要使用utf8x,它已经好几年没有维护了,而utf8正在积极开发。

您可以使用 的设置来玩\tabcolsep

在此处输入图片描述

答案2

你可以让 TeX 为你计算:

\documentclass[12pt,a4paper]{article}
\usepackage[left=2.5cm,right=2.5cm,headheight=14.5pt]{geometry}

\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[ngerman]{babel}

\usepackage[autolanguage, np]{numprint}
\usepackage{amsmath,amssymb,fancyhdr,array}

\pagestyle{fancy}

\usepackage{xintfrac, xintbinhex, xinttools}

\rhead{1608/1609 WS18/19}

\makeatletter
\def\DtoB@get@ND #1/#2[#3]{% #2 must be = 1 here, if input was in
                         % decimal notation
    \edef\DtoB@s{\xintiiSgn{#1}}%
    \edef\DtoB@A{\xintiiAbs{#1}}%
    \def\DtoB@L{#3}%
    \ifnum#3<\z@
       \let\DtoB@N\DtoB@A
       \edef\DtoB@D{\xintiiE{1}{-#3}}%
    \else
       \edef\DtoB@N{\xintiiE{\DtoB@A}{#3}}%
       \def\DtoB@D{1}%
    \fi
}%
\newcommand\ParseFromDecimalToIEEEBinary[1]{%
   % assume #1 is a decimal number (I will write code for fractions
   % another day)
   \expandafter\DtoB@get@ND\romannumeral0\xintrez{#1}%
   % we should here handle \DtoB@s = 0 but no time tonight, assume input non-zero
   \edef\DtoB@S@bit{\the\numexpr(1-\DtoB@s)/2}% 1 if number < 0, 0 if number > 0
   \edef\DtoB@U{\xintDecToBin{\DtoB@N}}%
   \edef\DtoB@V{\xintDecToBin{\DtoB@D}}%
   \edef\DtoB@Uk{\the\numexpr\expandafter\xintLength\expandafter{\DtoB@U}-\@ne}%
   \edef\DtoB@Vl{\the\numexpr\expandafter\xintLength\expandafter{\DtoB@V}-\@ne}%
   % next step should perhaps compare k and l first
   % important that we are comparing here two strings of 1s and 0s of
   % exact same length
   \ifnum\pdfstrcmp{\DtoB@U\romannumeral\xintreplicate{\DtoB@Vl}{0}}
                   {\DtoB@V\romannumeral\xintreplicate{\DtoB@Uk}{0}}=\m@ne
       \edef\DtoB@E{\the\numexpr\DtoB@Uk-\DtoB@Vl-\@ne}%
   \else
       \edef\DtoB@E{\the\numexpr\DtoB@Uk-\DtoB@Vl}%
   \fi
   \edef\DtoB@Eshifted@bits{\expandafter\@gobble
          \romannumeral0\xintdectobin{\the\numexpr \DtoB@E + 127 + 256\relax}}%
   \ifnum\DtoB@E>23
     \edef\DtoB@f@frac{\DtoB@A/\xintiiPow{2}{\DtoB@E-23}[\DtoB@L]}%
     %  use rather bintodec conversion of 10000...000 in above?
   \else
     \edef\DtoB@f@frac{\xintiiMul{\DtoB@A}{\xintiiPow{2}{23-\DtoB@E}}/1[\DtoB@L]}%
   \fi
   \edef\DtoB@f@int{\xintNum{\DtoB@f@frac}}% truncates to an int
   \edef\DtoB@M@bits{\expandafter\@gobble
                     \romannumeral0\xintdectobin{\DtoB@f@int}}%
   %\edef\DtoBresult{\DtoB@S@bit\DtoB@Eshifted@bits\DtoB@M@bits}%
   \let\IEEEsign\DtoB@S@bit
   \let\IEEEexponent\DtoB@Eshifted@bits
   \let\IEEEmantissa\DtoB@M@bits   
}%

\makeatother

\newcommand\AUFGABE[1]{%
\ParseFromDecimalToIEEEBinary{#1}%

\noindent
Gegeben sei die Dezimalzahl $Z_{10}=\np{#1}$.
\begin{itemize}
\item[a)] So richtig verstanden habe ich das Schema nicht...\\
% $Z_{32}=\left(-1\right)^1\cdot2^{135}\cdot\left(100001100,0110100\ldots\right)$
\item[b)] 
{\footnotesize\setlength{\tabcolsep}{1pt}\begin{tabular}[t]{|*{32}{w{c}{1em}|}}
\firsthline
\xintListWithSep{&}{\xintSeq[-1]{31}{0}}\\
\hline
S \romannumeral\xintreplicate{8}{&E}\romannumeral\xintreplicate{23}{&M}\\
\hline
\IEEEsign & \xintListWithSep{&}{\IEEEexponent} & \xintListWithSep{&}{\IEEEmantissa}\\
\hline
\end{tabular}\par}%
\end{itemize}
}

\begin{document}

\section*{Computersysteme II (01609) WS2018/19 EA 1}
\label{sec:Einsendeaufgabe 1}

\subsection*{Aufgabe 3 - Gleitkommadarstellung}

\AUFGABE{-208.40625}

\AUFGABE{1234.37892295}

\AUFGABE{37317.384038}

\end{document}

注意,我没有处理非规范化数字,并且输入不能为零!

我并没有真正对它进行压力测试,只是将上述的第一个和最后一个与在线转换器进行了比较。

按照我认为该a)项目所涉及的小数二进制表示法,我将其删除,但可以添加。

当然,您现在可以修改代码来处理任何其他类似的 IEEE 格式,并为指数和/或二进制尾数提供更多的空间。

在此处输入图片描述

注意:由于从十进制到二进制的转换可能不准确,我选择“向零截断”来选择二进制浮点数,也许四舍五入会更好(或者四舍五入到偶数)。

无错误检查输入导致溢出/下溢并且不处理非规范化数字。

另外由于暂时精力不足,没有进行扩展...


以下是根据 IEEE-754 格式的转换例程的更新,\DecimalToIEEEBinary具有任意、用户可配置的位数。我用一些 binary32、binary64 和一个 binary128 示例来说明它。请注意:

  • 由于时间不够,除了将一些转换结果与在线转换器的结果进行比较外,我没有对其进行测试,

  • 我还没有实现次正规数,或者溢出等等......

  • 我还没有实现不精确的标志等等……,

  • 输入允许任何分数(被宏接受xintfrac)但请注意结果是精确的四舍五入精确的将分数转换为最接近的二进制浮点数,它不是通过先转换分子然后转换分母然后进行浮点除法获得的(因为 IEEE-754 或其后来的 2008 版要求除法应该精确四舍五入,像 355/113 这样的结果并不奇怪,因为 355 和 113 中的每一个都精确表示,但是 355456.7/113456.3 可能会在 32 位二进制中给出不同的结果(大约 7 或 8 位小数精度)当在这里转换时或通过您的编程语言以单精度计算时,分子和分母已经有一些损失。

  • 例如,对于十进制数0.37,我相信普通语言会将这种转换为二进制浮点数并进行精确舍入(例如 Python)。如有疑问,请与\DecimalToIEEEBinary下面基于 xint 的内容进行比较,因为它是正确的(祈祷,我真的根本没有调试过那个东西,几乎没有测试过),因为它依赖于任意精度算法(Python 是一种具有这种任意精度整数算法的语言),

  • 因为我相信转换为二进制时的舍入模式应该是“舍入到最接近的数,平局取偶数”,所以我在这里实现了它。未经调试。(它很简单,但即使是最简单的 TeX 代码也需要程序员比 Python 或 C 或其他语言的代码集中 10 倍的注意力……)

代码:

\documentclass{article}
\usepackage{xintfrac}
\usepackage{xintbinhex}

\usepackage{xintexpr}% for one example only

\newcommand\IEEEexponentwidth{8}
\newcommand\IEEEtotalwidth{32}% 1 + exp with + mantissa (without leading bit) width 
\newcommand\IEEEupdate{%
  % for simplicity I assume here at most 30 exponent bits..., because I will
  % do computations with \numexpr for the exponent; I will not check
  % overflow conditions for these exponent computations although of course
  % I could as xint is arbitrary precision
  \edef\IEEEemax{\the\numexpr\xintiiPow{2}{\IEEEexponentwidth-1}-1}%
  \edef\IEEEepoweroftwo{\the\numexpr2*\IEEEemax+2}% needed internally
  \edef\IEEEemin{\the\numexpr-\IEEEemax+1}%
  \edef\IEEEebias{\IEEEemax}%
  \edef\IEEEprecision{\the\numexpr\IEEEtotalwidth-\IEEEexponentwidth}%
  \edef\IEEEmantissawidth{\the\numexpr\IEEEprecision-1}% leading bit is tacit
}%

\makeatletter
\catcode`_ 11
\catcode`! 3
\newcommand\IEEEsetup[1]{\D_to_ieeeB_parsekeys #1,=!,\IEEEupdate}%
\def\D_to_ieeeB_parsekeys #1=#2#3,{\ifx!#2\expandafter\D_to_ieeeB_parsedone\fi
    \csname IEEEsetup_key_\xint_zapspaces #1 \xint_gobble_i\endcsname
    \xint_firstoftwo
    {\PackageWarning{IEEEsetup}{The #1 key is unknown! ignoring}}{#2#3}%
    \D_to_ieeeB_parsekeys
}%
\def\D_to_ieeeB_parsedone #1\D_to_ieeeB_parsekeys {}%
\catcode`! 11 
\def\IEEEsetup_key_Ewidth  #1#2{\edef\IEEEexponentwidth}%
\def\IEEEsetup_key_totalwidth #1#2{\edef\IEEEtotalwidth}%

\IEEEsetup{Ewidth=8, totalwidth=32}

\newcommand\IEEEprintsetup{%
  Emax = \IEEEemax, Emin = \IEEEemin, P = \IEEEprecision.

  There is one leading sign bit, followed by \IEEEexponentwidth\ bits for the
  exponent (which is represented shifted by \IEEEebias), followed by
  \IEEEmantissawidth\ bits which represent the fractional part of the mantissa,
  its leading bit 1 being tacit.

  This setup is obtained by specifying Ewidth = \IEEEexponentwidth\ and
  totalwidth = \IEEEtotalwidth.

  % add some info about maximal representable, minimal normalized number,
  % minimal subnormal number

  When converting form decimal to binary we use rounding with ties going
  to even.

  Happy IEEEing! (thanks to xint library)
}%

\newcommand\IEEEclearflags{%
}%

\makeatletter
\catcode`_ 11
\def\DtoB@get@ND #1/#2[#3]{%
    \edef\DtoB@s{\xintiiSgn{#1}}%
    \edef\DtoB@A{\xintiiAbs{#1}}%
    \def\DtoB@L{#3}%
    \ifnum#3<\z@
       \let\DtoB@N\DtoB@A
       \edef\DtoB@D{\xintiiMul{#2}{\xintiiPow{5}{-#3}}}%
    \else
       \edef\DtoB@N{\xintiiMul{\DtoB@A}{\xintiiPow{5}{#3}}}%
       \def\DtoB@D{#2}%
    \fi
}%
\newcommand\DecimalToIEEEBinary[1]{%
   \expandafter\DtoB@get@ND\romannumeral0\xintrez{#1}%
   \ifnum\DtoB@s=0 \expandafter\DtoB@zero\else\expandafter\DtoB@a\fi
}%
\def\DtoB@zero{\def\IEEEresultSign{0}%
               \edef\IEEEresultExponent
                   {\romannumeral\xintreplicate{\IEEEexponentwidth}0}%
               \edef\IEEEresultMantissa
                   {\romannumeral\xintreplicate{\IEEEmantissawidth}0}%
}%
\def\DtoB@a{%
   \edef\DtoB@S@bit{\if1\DtoB@s0\else1\fi}%
   \edef\DtoB@U{\xintDecToBin{\DtoB@N}}%
   \edef\DtoB@V{\xintDecToBin{\DtoB@D}}%
   \edef\DtoB@Uk{\expandafter\xintLength\expandafter{\DtoB@U}}%
   \edef\DtoB@Vl{\expandafter\xintLength\expandafter{\DtoB@V}}%
   \ifnum\DtoB@Uk>\DtoB@Vl
     % important that we are comparing here two strings of 1s and 0s of
     % exact same length
     \ifnum\pdfstrcmp{\DtoB@U}%
                     {\DtoB@V\romannumeral\xintreplicate{\DtoB@Uk-\DtoB@Vl}{0}}=\m@ne
       \edef\DtoB@E{\the\numexpr\DtoB@Uk-\DtoB@Vl-\@ne+\DtoB@L}%
     \else
       \edef\DtoB@E{\the\numexpr\DtoB@Uk-\DtoB@Vl+\DtoB@L}%
     \fi
   \else
     \ifnum\pdfstrcmp{\DtoB@U\romannumeral\xintreplicate{\DtoB@Vl-\DtoB@Uk}{0}}%
                     {\DtoB@V}=\m@ne
       \edef\DtoB@E{\the\numexpr\DtoB@Uk-\DtoB@Vl-\@ne+\DtoB@L}%
     \else
       \edef\DtoB@E{\the\numexpr\DtoB@Uk-\DtoB@Vl+\DtoB@L}%
     \fi
   \fi
   \ifnum\DtoB@E<\IEEEemin\space
         \xint_dothis\DtoB@subnormal\fi
   \ifnum\DtoB@E>\IEEEemax\space
         \xint_dothis\DtoB@overflow\fi
   \xint_orthat\DtoB@b
}%
\def\DtoB@subnormal{%
SORRY SUBNORMAL NUMBERS NOT YET IMPLEMENTED
    \def\IEEEresultSign{0}%
    \edef\IEEEresultExponent{\romannumeral\xintreplicate{\IEEEexponentwidth}0}%
    \edef\IEEEresultMantissa{\romannumeral\xintreplicate{\IEEEmantissawidth}0}%
}%
\def\DtoB@b{%
   \edef\DtoB@Eshifted@bits{\expandafter\@gobble
          \romannumeral0\xintdectobin{\the\numexpr \DtoB@E + \IEEEebias
                                      + \IEEEepoweroftwo\relax}}%
   \edef\DtoB@F{\the\numexpr\DtoB@E-\DtoB@L}%
   \ifnum\DtoB@F>\IEEEmantissawidth % \space not really needed but let's
                                % terminate anyway properly the number for
                                % \ifnum test
     \let\DtoB@f@N\DtoB@N
     \edef\DtoB@f@D{\xintiiMul{\DtoB@D}{\xintiiPow{2}{\DtoB@F-\IEEEmantissawidth}}}%
   \else
     \edef\DtoB@f@N{\xintiiMul{\DtoB@N}{\xintiiPow{2}{\IEEEmantissawidth-\DtoB@F}}}%
     \let\DtoB@f@D\DtoB@D
   \fi
   % xint does not provide "rounding with tie going to even"
   % this is why we do some gymnastics here
   \def\DtoB@twicefplusone@N{\xintiiAdd{\DtoB@f@D}{\xintDouble{\DtoB@f@N}}}%
   % this would require xinttools, let's do without it
   % \xintAssign\xintiiDivision{\DtoB@twicefplusone@N}{\DtoB@f@D}\to\DtoB@Q\DtoB@R
   \edef\DtoB@temp{\xintiiDivision{\DtoB@twicefplusone@N}{\DtoB@f@D}}%
   \edef\DtoB@Q{\expandafter\xint_firstoftwo\DtoB@temp}%
   \edef\DtoB@R{\expandafter\xint_secondoftwo\DtoB@temp}%
   \edef\DtoB@f@int{\xintHalf{\DtoB@Q}}% \xintHalf truncates
   \xintiiifOdd{\DtoB@Q}%
     {% f is in an [n, n+.5) interval, Q=2n+1, rounding to n needs no correction
     }%
     {% f is in an [n+.5,n+1) interval, tie happens iff R=0
      \xintiiifZero{\DtoB@R}%
          {% we are in tie case, check oddness of n+1 value
           \xintiiifOdd{\DtoB@f@int}{\edef\DtoB@f@int{\xintDec{\DtoB@f@int}}}{}}%
          {% we are in (n+0.5, n+1), Q = 2n+2, rounding to n+1 was ok
          }%
     }%
   \edef\DtoB@M@bits{\expandafter\@gobble
                     \romannumeral0\xintdectobin{\DtoB@f@int}}%
   \let\IEEEresultSign\DtoB@S@bit
   \let\IEEEresultExponent\DtoB@Eshifted@bits
   \let\IEEEresultMantissa\DtoB@M@bits   
}%
\catcode`_ 8
\makeatother

\usepackage[T1]{fontenc}
\begin{document}

\IEEEsetup{Ewidth=8, totalwidth=32}
%\IEEEprintsetup

\DecimalToIEEEBinary{-208.40625}

$-208.40625 \mapsto \IEEEresultSign|\IEEEresultExponent|\IEEEresultMantissa$

\DecimalToIEEEBinary{1/3}

$\xintSignedFrac{1/3} \mapsto \IEEEresultSign|\IEEEresultExponent|\IEEEresultMantissa$

\DecimalToIEEEBinary{1/7}

$\xintSignedFrac{1/7} \mapsto \IEEEresultSign|\IEEEresultExponent|\IEEEresultMantissa$

\DecimalToIEEEBinary{0.7}

$0.7 \mapsto \IEEEresultSign|\IEEEresultExponent|\IEEEresultMantissa$

\DecimalToIEEEBinary{355/113}

$\xintSignedFrac{355/113} \mapsto \IEEEresultSign|\IEEEresultExponent|\IEEEresultMantissa$

\DecimalToIEEEBinary{3.141592653}

$3.141592653 \mapsto \IEEEresultSign|\IEEEresultExponent|\IEEEresultMantissa$

\vspace{2\baselineskip}

\IEEEsetup{Ewidth=11, totalwidth=64}

\IEEEprintsetup

\DecimalToIEEEBinary{-208.40625}

$-208.40625 \mapsto \IEEEresultSign|\IEEEresultExponent|\IEEEresultMantissa$

\DecimalToIEEEBinary{1/3}

$\xintSignedFrac{1/3} \mapsto \IEEEresultSign|\IEEEresultExponent|\IEEEresultMantissa$

\DecimalToIEEEBinary{1/7}

$\xintSignedFrac{1/7} \mapsto \IEEEresultSign|\IEEEresultExponent|\IEEEresultMantissa$

\DecimalToIEEEBinary{0.7}

$0.7 \mapsto \IEEEresultSign|\IEEEresultExponent|\IEEEresultMantissa$

\DecimalToIEEEBinary{355/113}

$\xintSignedFrac{355/113} \mapsto \IEEEresultSign|\IEEEresultExponent|\IEEEresultMantissa$

\DecimalToIEEEBinary{3.141592653}

$3.141592653 \mapsto \IEEEresultSign|\IEEEresultExponent|\IEEEresultMantissa$

\DecimalToIEEEBinary{2.718281828}

$2.718281828 \mapsto \IEEEresultSign|\IEEEresultExponent|\IEEEresultMantissa$


\vspace{2\baselineskip}

\IEEEsetup{Ewidth=15, totalwidth=128}

\DecimalToIEEEBinary{3.141592653}

3.141592653 is represented by:

1bit for sign: \IEEEresultSign

15bits for exponent (biased) \IEEEresultExponent

112bits for mantissa (a leading 113th bit is left tacit):

\def\allowsplits #1{\ifx #1\relax \else #1\hskip 0pt plus 1pt\relax \expandafter\allowsplits\fi}%
\def\printnumber #1{\expandafter\allowsplits \romannumeral-`0#1\relax }%

\noindent\printnumber\IEEEresultMantissa\relax

Here is the start of decimal expansion corresponding to this binary approximation:

\noindent\printnumber{\xinttheexpr
  trunc(2+\xintBinToDec{\IEEEresultMantissa}/2^111, 60)\relax}\relax\dots

\xintDigits:=48;

The absolute error is about \xintthefloatexpr[8] 3.141592653 - 2 -
\xintBinToDec{\IEEEresultMantissa}/2^111\relax, as expected we have about 34
exact decimal digits (although here a long sequence of 9s has appeared).

\end{document}

在此处输入图片描述



第三个版本排版方式可以手工完成。

  • 这里只说明了转换为 32 位,

  • 未处理次正规数,

  • 并非所有分支都经过了测试(特别是我已经实现但尚未测试“平局归偶数”规则)。

使用风险自负。

\documentclass[ngerman]{article}
\usepackage{xintfrac}
\usepackage{xintbinhex}
\usepackage{xinttools}
%%%%\usepackage{xintexpr}% pour un exemple
\usepackage{babel}
\usepackage[np, autolanguage]{numprint}

\makeatletter
\newcommand\TypesetIEEExxxiibitsConversion[1]{%
    \edef\TCI@input{#1}%
    We are going to compute the IEEE-754 32bits representation of the decimal
    number $\np{\xintDecToString{\TCI@input}}_{10}$.
    
    \expandafter\TCI@a\romannumeral0\xintrez{\TCI@input}%
}%
\def\TCI@a #1/1[#2]{%
    \edef\TCI@num@s{\xintiiSgn{#1}}%
    \edef\TCI@num@A{\xintiiAbs{#1}}%
    \def\TCI@num@L{#2}%
    \xintiiifZero\TCI@num@A
      \TCI@iszero
      \TCI@b
}%
\def\TCI@iszero{Well, that was easy, this number vanishes. The 32 bits of its
  representation are all 0s. Done.}
\def\TCI@b{%
    \ifnum\TCI@num@s>0
      This number is positive, the leftmost bit is thus 0.\par
      \def\TCISignBit{0}%
   \else
      This number is negative, the leftmost bit is thus 1.\par
      \def\TCISignBit{1}%
   \fi
   \TCI@c
}%
\def\TCI@c{%
    \edef\TCI@num@int{\xintTTrunc{\TCI@num@A/1[\TCI@num@L]}}%
    \edef\TCI@num@frac
        {\xintREZ{\xintSub{\TCI@num@A/1[\TCI@num@L]}{\TCI@num@int}}}%
    \edef\TCI@num@int@bin{\xintDecToBin\TCI@num@int}%
    The integer part is $\TCI@num@int_{10}$, whose conversion to binary is:

    $\TCI@num@int@bin_2$.

    \edef\TCI@num@int@bin@length{\expandafter\xintLength\expandafter
                                 {\TCI@num@int@bin}}%
    \ifnum\TCI@num@int@bin@length>24
     \expandafter\TCI@A
    \else
     \expandafter\TCI@B
    \fi
}%
\def\TCI@A{%
    This occupies \TCI@num@int@bin@length\ binary digits.
    We need to round to only 24 bits of precision.
    \edef\TCI@bin@short{\xintKeepUnbraced{24}{\TCI@num@int@bin}}%
    \edef\TCIMantissaBits{\expandafter\@gobble\TCI@bin@short}% temporary
    \edef\TCI@bin@therest{\xintTrimUnbraced{24}{\TCI@num@int@bin}}%
    \edef\TCI@bin@E{\the\numexpr \TCI@num@int@bin@length-1}%
    The rest after the 24 leading bits $\TCI@bin@short_2$ is $\TCI@bin@therest_2$
    which has $\the\numexpr\TCI@num@int@bin@length-24$ binary digit(s)%
    \xintiiifZero{\TCI@num@frac}% abuse of ii usage (private note)
      \TCI@Aa
      \TCI@Ab
}%
\def\TCI@Aa{%
      . We compare this remainder to one half of a unit in the last place i.e.
      with $1\romannumeral\xintreplicate{\TCI@num@int@bin@length-25}{0}_2$.
      \edef\TCI@bin@halfoneULP{\xintiiPow{2}{\TCI@num@int@bin@length-25}}%
      \xintiiifCmp{\TCI@bin@therest}{\TCI@bin@halfoneULP}
      \TCI@Aaa
      \TCI@Aab
      {It is greater so \TCI@roundup}
}%
\def\TCI@Aaa{%
    There is strictly less than half a u.l.p. (unit in the last place) left, so this
    is it.
   \TCI@finish
}%
\def\TCI@Aab{%
    We are in a tie situation. We must round to even.
    \xintiiifOdd{\TCI@bin@short}% 
    \TCI@Aaba
    \TCI@Aabb
}%
\def\TCI@Aaba{%
     \edef\TCIMantissaBits
          {\expandafter\@gobble\romannumeral0%
           \xintdectobin{\xintInc{\xintBinToDec{\TCI@bin@short}}}}%
    This means here that we must increase by one from $\TCI@bin@short$
    to $1\TCIMantissaBits_2$.

    The exponent is $e = \TCI@bin@E$.
     \xintiiifZero{\xintiNum{\TCIMantissaBits}}
        \TCI@roundingupwenttopoweroftwo
        \TCI@finish
}%
\def\TCI@Aabb{%
    Our leading bits already correspond to an even number, so this is it.
    \TCI@finish
}%
\def\TCI@Ab{ (and there is also fractional part
    $\np{\xintDecToString{\TCI@num@frac}}_{10}$). We compare this remainder to
    one half of a unit in the last place i.e. with
    $1\romannumeral\xintreplicate{\TCI@num@int@bin@length-25}{0}_2
    =2^{\the\numexpr\TCI@num@int@bin@length-25}$.
    \edef\TCI@bin@halfoneULP{\xintiiPow{2}{\TCI@num@int@bin@length-25}}%
    \xintiiifCmp{\TCI@bin@therest}{\TCI@bin@halfoneULP} \TCI@Aba \TCI@Abb
    \TCI@Abc
}%
\def\TCI@Aba{%
    It is less (and the fractional part can not change that), so this is it.
    \TCI@finish
}%
\def\TCI@Abb{%
    The integer remainder is exactly one half of a ULP but there is still a
    \emph{non-vanishing fractional part}. Thus, \TCI@roundup
}%
\def\TCI@Abc{%
    We have more than one half of a u.l.p. Hence, \TCI@roundup }%
\def\TCI@B{%
    \xintiiifZero\TCI@num@int \TCI@Bloop \TCI@C
}%
\def\TCI@Bloop{%
    The integral part vanishes. We multiply by 2 the input as many times as is
    needed to obtain a non-vanishing integral part, i.e. the input will now
    become a decimal number at least $1$ and less than $2$. I.e. we must multiply
    $\TCI@num@A$ by $2$ enough times for it to become at least equal to
    $10^{\the\numexpr-\TCI@num@L}$. 

    \def\TCI@bin@E{0}
    \xintloop
    \edef\TCI@num@A{\xintDouble{\TCI@num@A}}%
    \edef\TCI@bin@E{\the\numexpr\TCI@bin@E-1}%
    \unless
    \ifnum-\TCI@num@L<\expandafter\xintLength\expandafter{\TCI@num@A}\space
    \repeat

    It turns out we had to do this $\the\numexpr-\TCI@bin@E$ times, and we are
    now looking at:

    $\np{\xintDecToString{\TCI@num@A/1[\TCI@num@L]}}_{10}$.

    The exponent will thus be $\TCI@bin@E$ (or exceptionally one more if we are
    very close to $2$ here, you can probably tell better than me because I am
    too lazy to check immediately at this stage).

    \edef\TCI@poweroftwo{\xintiiPow{2}{24}}%
    \def\TCI@num@int@bin@length{25}%
    We now multiply our (already multiplied) input by $2^{24}=\TCI@poweroftwo$,
    in order for the integral part to occupy exactly 25 binary digits (we will
    use the last one to decide in which direction goes the rounding to nearest
    binary float).
    
    \edef\TCI@num@A{\xintiiMul{\TCI@poweroftwo}{\TCI@num@A}}%
    Our modified input is $\np{\xintDecToString{\TCI@num@A/1[\TCI@num@L]}}_{10}$\par
    \TCI@D
}%
\def\TCI@C{%
    This occupies \TCI@num@int@bin@length\ binary digit(s).
    \edef\TCI@poweroftwo{\xintiiPow{2}{25-\TCI@num@int@bin@length}}%
    \edef\TCI@Eshift{\the\numexpr25-\TCI@num@int@bin@length}%
    \edef\TCI@bin@E{\the\numexpr24-\TCI@Eshift}%
    \def\TCI@num@int@bin@length{25}%
    In order to work mainly with integers, we first multiply our input by
    $2^{\TCI@Eshift}=\TCI@poweroftwo$, then the integral part will occupy
    25 binary digits (we will use the last one to decide the rounding to
    nearest binary float). The final exponent will be
    $\TCI@bin@E$, or perhaps one unit more if some rounding to next
    power of two is needed.

    \edef\TCI@num@A{\xintiiMul{\TCI@poweroftwo}{\TCI@num@A}}%
    Our modified input is $\np{\xintDecToString{\TCI@num@A/1[\TCI@num@L]}}_{10}$\par
    \TCI@D
}
\def\TCI@D{%
    \edef\TCI@num@int{\xintTTrunc{\TCI@num@A/1[\TCI@num@L]}}%
    \edef\TCI@num@frac
        {\xintREZ{\xintSub{\TCI@num@A/1[\TCI@num@L]}{\TCI@num@int}}}%
    \edef\TCI@num@int@bin{\xintDecToBin\TCI@num@int}%

    The integer part in binary is $\TCI@num@int@bin_2$ and occupies as expected
    25 bits.

    \def\TCI@num@int@bin@length{25}%
    We need to round to only 24 bits of precision.
    \edef\TCI@bin@short{\xintKeepUnbraced{24}{\TCI@num@int@bin}}%
    \edef\TCIMantissaBits{\expandafter\@gobble\TCI@bin@short}% temporary
    \edef\TCI@bin@therest{\expandafter\xintLastItem\expandafter{\TCI@num@int@bin}}%
    The 25th bit is $\TCI@bin@therest_2$%
    \xintiiifZero{\TCI@num@frac}% abuse of ii usage (private note)
      \TCI@Aa
      \TCI@Ab
}%
\def\TCI@roundup{%
     we must increase the mantissa by one unit in the last place, obtaining
     \edef\TCIMantissaBits
          {\expandafter\@gobble\romannumeral0%
           \xintdectobin{\xintInc{\xintBinToDec{\TCI@bin@short}}}}%
     $1\TCIMantissaBits_2$.
     The exponent is $e = \TCI@bin@E$.
     \xintiiifZero{\xintiNum{\TCIMantissaBits}}
        \TCI@roundingupwenttopoweroftwo
        \TCI@finish
}%
\def\TCI@roundingupwenttopoweroftwo{%
    Attention that the rounding went to a power of two, so we must increase
    it by $1$. The mantissa will be with 23 zeros (because the leading
    bit is tacit).

    \edef\TCI@bin@E{\the\numexpr\TCI@bin@E+1}%
    \edef\TCIMantissaBits{\romannumeral\xintreplicate{23}{0}}%
    \TCI@finish
}%
\def\TCI@finish{\par
    The stored (biased) exponent will be $\TCI@bin@E + 127 =
     \the\numexpr\TCI@bin@E + 127\relax$  which in binary
     gives 
     \edef\TCIExponentBits{\expandafter\@gobble\romannumeral0%
       \xintdectobin{\the\numexpr\TCI@bin@E + 127 +
         256\relax}}%
     $\TCIExponentBits$.

     In total: $\TCISignBit|\TCIExponentBits|\TCIMantissaBits$.\par
}%
\makeatother

\usepackage[T1]{fontenc}
\begin{document}

\TypesetIEEExxxiibitsConversion{0.000000000123}
% 
% 0|01011110|00001110011110101101100
% 0 01011110 00001110011110101101100

\clearpage
\TypesetIEEExxxiibitsConversion{-0.0000000001234567}
% 1|01011110|00001111011110111111001
% 1 01011110 00001111011110111111001

\clearpage
\TypesetIEEExxxiibitsConversion{-1234.567}
% 1|10001001|00110100101001000100101
% 1 10001001 00110100101001000100101

\clearpage
\TypesetIEEExxxiibitsConversion{-0.00000000000000001234567}
% 1|01000110|11000111011110011000111
% 1 01000110 11000111011110011000111

\clearpage
% hmm pénible l'input car \np ne veut pas de /, donc \xintDecToString
% doit être utilisé uniquement avec /1
% 2^24-0.5
% 1 - 2^{-25}
% (2^{25}-1)/2^{25}
% (2^{25}-1)*5^{25}/10^{25}
\TypesetIEEExxxiibitsConversion
   {\xintiiMul{\xintDec{\xintiiPow{2}{25}}}{\xintiiPow{5}{25}}[-25]}

\clearpage

%  8388608 = 2**23
% 16777216 = 2**24
% 12345678 - 0.5
% 12345677.5
% 12345677.5/1024
% 12345677.5*5**10/10**10
% \typeout{\xintDecToString{\xinttheexpr 12345677.5*5**10[-10]\relax}}
% 12056.32568359375
\TypesetIEEExxxiibitsConversion{12056.32568359375}
% 0|10001100|01111000110000101001110
% 0 10001100 01111000110000101001110

\clearpage

%\typeout{\xintDecToString{\xinttheexpr 12345676.5*5**12[-12]\relax}}
% 12056.32568359375
\TypesetIEEExxxiibitsConversion{3014.0811767578125}%
% 0|10001010|01111000110000101001100
% 0 10001010 01111000110000101001101

\end{document}

在此处输入图片描述

在此处输入图片描述

在此处输入图片描述

在此处输入图片描述

相关内容