What are the various units (ex, em, in, pt, bp, dd, pc) expressed in mm?
Here is a variant on Herbert's answer, using \dimexpr
instead (inspired from the thread \ifnum for real numbers of comp.text.tex), which allows to do conversions in a purely expandable way. The syntax is \convertto{mm}{1pt}
to convert 1pt
in mm
:
\makeatletter
\def\convertto#1#2{\strip@pt\dimexpr #2*65536/\number\dimexpr 1#1}
\makeatother
The results are not quite the same as with the printlen package, probably due to the fact that \dimexpr
performs arithmetic slightly differently from TeX. Here's a table showing all the converted lengths (I omitted sp
to avoid arithmetic overflows):
\documentclass[a4paper]{article}
\usepackage{array}
\usepackage[hmargin=2cm]{geometry}
\makeatletter
%http://groups.google.com/group/comp.text.tex/msg/7e812e5d6e67fcc5
\def\convertto#1#2{\strip@pt\dimexpr #2*65536/\number\dimexpr 1#1}
\makeatother
\begin{document}
\begin{center}\begin{tabular}
{>{\def\colunit{pt}}l<{\convertto{\rowunit}{1\colunit}}
>{\def\colunit{mm}}l<{\convertto{\rowunit}{1\colunit}}
>{\def\colunit{cm}}l<{\convertto{\rowunit}{1\colunit}}
>{\def\colunit{ex}}l<{\convertto{\rowunit}{1\colunit}}
>{\def\colunit{em}}l<{\convertto{\rowunit}{1\colunit}}
>{\def\colunit{bp}}l<{\convertto{\rowunit}{1\colunit}}
>{\def\colunit{dd}}l<{\convertto{\rowunit}{1\colunit}}
>{\def\colunit{pc}}l<{\convertto{\rowunit}{1\colunit}}
>{\def\colunit{in}}l<{\convertto{\rowunit}{1\colunit}}
>{\bfseries}l}
\multicolumn{1}{l}{\bfseries 1pt} & \multicolumn{1}{l}{\bfseries 1mm} & \multicolumn{1}{l}{\bfseries 1cm} & \multicolumn{1}{l}{\bfseries 1ex} & \multicolumn{1}{l}{\bfseries 1em} & \multicolumn{1}{l}{\bfseries 1bp} & \multicolumn{1}{l}{\bfseries 1dd} & \multicolumn{1}{l}{\bfseries 1pc} & \multicolumn{1}{l}{\bfseries 1in} & \\
\gdef\rowunit{pt} & & & & & & & & & \rowunit\\
\gdef\rowunit{mm} & & & & & & & & & \rowunit\\
\gdef\rowunit{cm} & & & & & & & & & \rowunit\\
\gdef\rowunit{ex} & & & & & & & & & \rowunit\\
\gdef\rowunit{em} & & & & & & & & & \rowunit\\
\gdef\rowunit{bp} & & & & & & & & & \rowunit\\
\gdef\rowunit{dd} & & & & & & & & & \rowunit\\
\gdef\rowunit{pc} & & & & & & & & & \rowunit\\
\gdef\rowunit{in} & & & & & & & & & \rowunit\\
\end{tabular}\end{center}
\end{document}
incipit (2017)
The precise rules how TeX inputs a dimension expressed in a certain unit are commented in these two posts:
Why pdf file cannot be reproduced?
What value TeX uses as its minimal unit
The underlying thing is that internally all dimensions are integer multiples of sp
unit, hence there must be some conversion done. A few salient points:
the set of those internal dimensions obtainable from a specification in
cm
has non empty symmetric difference with the set of those dimensions obtainable from a dimension within
as unit. This is important if one intents to use\ifdim
tests. This is a core TeX aspect and will not be changed by any higher level interface for testing dimension equality.when expressing a dimension in a given unit
<unit>
, the granularity is1/65536<unit>
and using more than five digits after the decimal mark can bring only a one-shot change. But it is hard to guess the borderline: nothing can change beyond 17 decimal digits, but the result obtained from 17 decimal digits is not necessarily the same as the one obtained from rounding these 17 decimal digits to only 5 decimal digits. As this might surprise people I am providing here some examples you can try out:0.22222pt (from 2/9) gives 14563sp but 0.22222222222222222pt gives 14564sp. One must use 0.22223pt to get also 14654sp.
1.53333pt (from 23/15) gives 100488sp but 1.53333333333333333pt gives 100489sp. One must use 1.53334pt to get also 100489sp.
Yes, using 0.66667pt is the correct choice, but this is a bit an accidental fact as the two examples above show: sometimes one should round in the opposite direction to get what the full specification with 17digits would have given. (unfortunately it appears I have lost a file where I had tested these things but I remember that my testing revealed that counter-intuitive rounding was needed in roughly
10%
of the tested cases, built-up using small fractions like the above ones).
The bigger the dimension unit, the less precise the inner representation. Hence using in
is a less precise input method than using cm
which is less precise than using pt
. For example using em
typically means you ave a 10sp
granularity, and there is no way to go below that, even with using 17 decimal digits in the expression of the dimension using with em
unit. Using pt
ensures the minimal 1sp
granularity.
Regarding the Didot point, there is a more-detailed examination in a section of the xint manual.
(end of 2017 added contents)
Here is another type of table. It gives the exact irreducible conversion factors between units (em
and ex
are the special font dependent cases; for them I use \dimexpr
but this seems not to be a too good idea, it would perhaps be better to get them from the the suitable \fontdimen
parameters).
After the exact table I also give a table with values rounded to five decimal places.
Update: Following a suggestion done in a comment, the tables first. There seems to be something fishy with the em
: it seems to be exactly 10pt+1sp
and not the more intuitively reasonable 10pt
. I would have guessed it should be exactly 10pt
in that case with the default CM fonts. But I just tested with \the\fontdimen6\font
and it also gave to my surprise 10.00002pt
, (compiled with pdftex).
Update: before turning off the internet for a while, I checked the em
for bold, slanted and teletype: respectively 11.5pt-4sp
, 10pt+1sp
and 10.5pt-7sp
. Perhaps some font expert could explain what is the mechanism? perhaps an underlying conversion from big points at some stage in the font creation process?
Update: I have played a bit with continued fractions, and a good approximation to 1dd
is 107/100pt
which is clear also from the decimal expansion in the second table, and a very good fraction approximation to 1dd
in millimeters is 44/117
(the previous centered convergent is 3/8=0.375
which is already quite good compared to the exact 0.3760650274...
value of 1dd
in mm
).
\documentclass{article}
\usepackage{xintfrac}
% http://www.ctan.org/tex-archive/macros/generic/xint
% This code was compiled with the version 1.06a of the xint
% bundle dated 2013/05/09, which should appear soon on CTAN.
% The current CTAN version 1.06 should be also OK for this.
\usepackage{array}
\usepackage[hmargin=.5cm]{geometry}
% Conversions to the basic dimension, chosen to be the centimeter
% Base dimension: 1cm
\def\onecm {1}
\def\onemm {1/10}
\def\onein {2.54}
%% \def\onept {\xintMul {1/72.27}{\onein}}
%% simpler:
\def\onept {2.54/72.27}
%% \def\onebp {\xintMul {1/72}{\onein}}
%% simpler:
\def\onebp {2.54/72}
\def\onepc {\xintMul {12}{\onept}}
\def\oneex {\xintMul {\the\numexpr\dimexpr 1ex\relax\relax}{\onesp}}
\def\oneem {\xintMul {\the\numexpr\dimexpr 1em\relax\relax}{\onesp}}
\def\onedd {\xintMul {1238/1157}{\onept}}
% 1157 dd = 1238 pt I take this conversion factor from the TeXBook
% Wikipedia has other conversion factors, but of course here we
% have to do it the TeX way.
\def\onecc {\xintMul {12}{\onedd}}
\def\onesp {\xintMul {1/65536}{\onept}}
% Routines with delimited arguments, the good old TeX way
% (completely expandable)
\makeatletter
% exact conversion to an irreducible fraction:
% example: \convertexactly 126.2772pt\to {bp}
% and `pt' may be a macro expanding to it.
% idem for {bp} which may be a macro expanding to bp
\def\convertexactly #1\to #2%
{\xintIrr{\convertexactly@ #1\to {#2}}}%
% Variant with rounding at a number of decimal places
% given by first argument.
\def\convertwithrounding #1#2\to #3%
{\xintRound {#1}{\convertexactly@ #2\to {#3}}}%
% routines doing the job:
\def\convertexactly@ #1\to
{%
\romannumeral0%
\expandafter\expandafter\expandafter
\convertexactly@a
\xintReverseOrder {#1}\Z
}%
\def\convertexactly@a #1%
{%
\ifcat\noexpand #1\relax
\expandafter \convertexactly@b
\else
\expandafter \convertexactly@c
\fi #1%
}%
\def\convertexactly@b #1#2\Z #3%
{%
\xintdiv {\xintMul {\xintReverseOrder{#2}}{\csname one#1\endcsname}}
{\csname one#3\endcsname}%
}%
\def\convertexactly@c #1#2#3\Z #4%
{%
\xintdiv {\xintMul {\xintReverseOrder{#3}}{\csname one#2#1\endcsname}}
{\csname one#4\endcsname}%
}%
\makeatother
\def\bigstrut {\vbox to 24pt{}\vbox to 12pt{}}%
\begin{document}
Testing:
72.27pt is exactly \convertexactly 72.27pt\to {bp}bp
1/2.54in is exactly \convertexactly 1/2.54in\to {mm}mm
10pt is exactly (for this font) \convertexactly 10pt\to {ex}ex,
or approximately \convertwithrounding{20}10pt\to {ex}ex
10pt is exactly (for this font) \convertexactly 10pt\to {em}em,
or approximately \convertwithrounding{20}10pt\to {em}em
1em is exactly (for this font) \convertexactly
1em\to {pt}pt, or approximately
\convertwithrounding{20}1em\to {pt}pt.
And indeed
\verb+\the\dimexpr 1em\relax+ gives \the\dimexpr 1em\relax{} and
\verb+\the\fontdimen6\font+ gives \the\fontdimen6\font
1ex is exactly (for this font) \convertexactly 1ex\to {pt}pt, or approximately
\convertwithrounding{20}1ex\to {pt}pt.
And indeed
\verb+\the\dimexpr 1ex\relax+ gives \the\dimexpr 1ex\relax.
\def\tableentry{$\displaystyle\xintFrac{\convertexactly 1\colunit\to\rowunit}$\bigstrut}
\begin{center}\begin{tabular}
{>{\def\colunit{pt}}l<{\tableentry}
>{\def\colunit{mm}}l<{\tableentry}
>{\def\colunit{cm}}l<{\tableentry}
>{\def\colunit{ex}}l<{\tableentry}
>{\def\colunit{em}}l<{\tableentry}
>{\def\colunit{bp}}l<{\tableentry}
>{\def\colunit{dd}}l<{\tableentry}
>{\def\colunit{pc}}l<{\tableentry}
>{\def\colunit{in}}l<{\tableentry}
>{\bfseries}l}
\multicolumn{1}{l}{\bfseries 1pt} & \multicolumn{1}{l}{\bfseries 1mm} &
\multicolumn{1}{l}{\bfseries 1cm} & \multicolumn{1}{l}{\bfseries 1ex} &
\multicolumn{1}{l}{\bfseries 1em} & \multicolumn{1}{l}{\bfseries 1bp} &
\multicolumn{1}{l}{\bfseries 1dd} & \multicolumn{1}{l}{\bfseries 1pc} &
\multicolumn{1}{l}{\bfseries 1in} & \\
\gdef\rowunit{pt} & & & & & & & & & \rowunit\\
\gdef\rowunit{mm} & & & & & & & & & \rowunit\\
\gdef\rowunit{cm} & & & & & & & & & \rowunit\\
\gdef\rowunit{ex} & & & & & & & & & \rowunit\\
\gdef\rowunit{em} & & & & & & & & & \rowunit\\
\gdef\rowunit{bp} & & & & & & & & & \rowunit\\
\gdef\rowunit{dd} & & & & & & & & & \rowunit\\
\gdef\rowunit{pc} & & & & & & & & & \rowunit\\
\gdef\rowunit{in} & & & & & & & & & \rowunit\\
\end{tabular}\end{center}
\clearpage
\def\tableentry{\convertwithrounding {5}1\colunit\to\rowunit}
\begin{center}\begin{tabular}
{>{\def\colunit{pt}}l<{\tableentry}
>{\def\colunit{mm}}l<{\tableentry}
>{\def\colunit{cm}}l<{\tableentry}
>{\def\colunit{ex}}l<{\tableentry}
>{\def\colunit{em}}l<{\tableentry}
>{\def\colunit{bp}}l<{\tableentry}
>{\def\colunit{dd}}l<{\tableentry}
>{\def\colunit{pc}}l<{\tableentry}
>{\def\colunit{in}}l<{\tableentry}
>{\bfseries}l}
\multicolumn{1}{l}{\bfseries 1pt} & \multicolumn{1}{l}{\bfseries 1mm} &
\multicolumn{1}{l}{\bfseries 1cm} & \multicolumn{1}{l}{\bfseries 1ex} &
\multicolumn{1}{l}{\bfseries 1em} & \multicolumn{1}{l}{\bfseries 1bp} &
\multicolumn{1}{l}{\bfseries 1dd} & \multicolumn{1}{l}{\bfseries 1pc} &
\multicolumn{1}{l}{\bfseries 1in} & \\
\gdef\rowunit{pt} & & & & & & & & & \rowunit\\
\gdef\rowunit{mm} & & & & & & & & & \rowunit\\
\gdef\rowunit{cm} & & & & & & & & & \rowunit\\
\gdef\rowunit{ex} & & & & & & & & & \rowunit\\
\gdef\rowunit{em} & & & & & & & & & \rowunit\\
\gdef\rowunit{bp} & & & & & & & & & \rowunit\\
\gdef\rowunit{dd} & & & & & & & & & \rowunit\\
\gdef\rowunit{pc} & & & & & & & & & \rowunit\\
\gdef\rowunit{in} & & & & & & & & & \rowunit\\
\end{tabular}\end{center}
\end{document}
Actually the two approximations, given with 20
places after the decimal mark, for 1em
and 1ex
, are exact, the denominators are powers of 2, the complete decimal expansion only has zeros after those shown. I still do not quite understand why 1em
turns out to be 655361sp
and not 655360sp=10pt
in the case of the CM font. This 10pt+1sp
is strange.
And TeX's nice arithmetic can be seen .. ;-)
\documentclass{article}
\usepackage{printlen}
\parindent=0pt
\newlength\Length \Length=1cm
\begin{document}
\tabular{p{2cm}p{2cm}}
\mbox{--- 1cm ---}
\uselengthunit{cm}\printlength{\Length}\
\uselengthunit{mm}\printlength{\Length}\
\uselengthunit{in}\printlength{\Length}\
\uselengthunit{pt}\printlength{\Length}\
\uselengthunit{bp}\printlength{\Length}\
\uselengthunit{sp}\printlength{\Length}\
\uselengthunit{pc}\printlength{\Length}\
&
\mbox{--- 1em ---}
\Length=1em
\uselengthunit{cm}\printlength{\Length}\
\uselengthunit{mm}\printlength{\Length}\
\uselengthunit{in}\printlength{\Length}\
\uselengthunit{pt}\printlength{\Length}\
\uselengthunit{bp}\printlength{\Length}\
\uselengthunit{sp}\printlength{\Length}\
\uselengthunit{pc}\printlength{\Length}
\endtabular
\end{document}