How can one determine the length of the different units (measured 1ex
, 1em
, 1in
, 1pt
, 1bp
, 1dd
, 1pc
) in mm
?
9 Answers
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}
-
Any particular reason why you do not do:
\def\convertto#1#2{\strip@pt\dimexpr #2*65536/\number\dimexpr 1#1\ #1}
or\def\convertto#1#2{\strip@pt\dimexpr #2*65536/\number\dimexpr 1#1\relax\ #1}
to include the unit in the expanded output? Oct 20, 2016 at 10:58 -
1Of course, the results for ex and em depend on the current font .. Nov 18, 2019 at 22:16
-
It's interesting to note that TeX adopts a quasi-decimal metric system.– gboffiJul 3, 2020 at 15:40
-
@gboffi It's a consequence of the internal representation of dimensions in TeX. Everything is, at its lowest level an integer (portable floating point arithmetic wasn't standardized until 1985, well after TeX82's release, so Knuth had to implement his algorithms ex nihilo) and dimensions are represented in integer quantities of sp = 1/65536pt. This, plus the conversions to decimal end up with mild rounding errors that can show up in anything other than the conversions between sp, pt and pc (and possibly ex/em depending on their values) Jul 30, 2021 at 13:34
incipit (2017)
The precise rules how TeX inputs a dimension expressed in a certain unit are commented in these two posts:
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.
-
+1, neat! Two suggestions: Use the
parskip
package to get some space between the “sentences”. Put the picture first in your answer so that it’s closer to your remarks; unlike in most other answers, the output seems more important than the code here. May 9, 2013 at 21:02 -
-
@kissmyarmpit sorry for delay. The maximal input for a dimension expressed in pt is
16383.99999237060546874pt
. Anything bigger creates a dimension too large error. This corresponds to1073741823sp
(2^30-1
). In fact the minimal spec which gives this maximal allowed value is16383.99997711181640625pt
. Anything smaller gives at most2^30-2 sp
.– user4686Mar 27, 2017 at 8:14 -
@kissmyarmpit using five decimal digits, both
16383.99998pt
and16383.99999pt
give the maximal dimension, but not16383.99997pt
. And\the\maxdimen
outputs16383.99998pt
. But as I said16383.99999pt
is still acceptable (try\the\dimexpr 16383.99999pt\relax
.) but not16383.999993pt
.– user4686Mar 27, 2017 at 8:22
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}
-
10
-
111ex is supposed to be the height of 'x', and 1em is supposed to the width of 'm' -- so they should vary with the font and font size. Do they?– frabjousJan 5, 2011 at 2:27
-
10@frabjous: 1em is the width of M and sure they vary– user2478Jan 5, 2011 at 6:57
-
4Thanks, Herbert. That's an important thing to note for the question asked.– frabjousJan 5, 2011 at 19:31
-
1@frabjous: This isn't quite right for fonts with narrow M's, see en.wikipedia.org/wiki/Em_%28typography%29– CaramdirJan 5, 2011 at 23:33
- An inch is 25.4 mm.
- For TeX, 1 pt is 1/72.27 in, which is 0.351459804 mm.
- For most other software, 1 pt is 1/72 in, which is 0.352777778 mm. Also called Postscript Point, in TeX this is called a big point (bp).
- ex and em are not a fixed length, as they depend on the fontsize. (See this question.)
Edit: Herberts answer shows you how to find the length of 1 ex and 1em in your document.
-
You have a small typo here. 1 TeX point is 1/72.27 inch (not 1/72.72 inch). BTW I think it is not widely known that Google's calculator supports both points. Exemplary searches:
1 TeX point - 1/72.27 inch
,1 PS point - 1/72 inch
, both obviously returning 0.– przemocJun 27, 2011 at 20:37 -
@przemoc: Indeed, you're right, thanks. I don't think I'll edit the post though, that'll bring the question to the top of the list again, and the correct value is in the accepted answer anyway. Jun 27, 2011 at 20:54
-
You shouldn't care about such small detail as moving your answer to the top, because keeping the mistake is definitely bad. Moreover, Ctrl+F on 1/72.27 returns only my comment, which is pretty bad, because it is formal definition of point in TeX and should be clearly mentioned somewhere, i.e. in the main text of answer, not in a comment.– przemocJun 27, 2011 at 21:06
-
-
1I’ve just recherched point sizes and history, because I have found conflicting information about the Teχ point. It is in fact 1/72.27 of the modern (25.4 mm) inch, or 800/803 of the PostScript point (1/72 inch). Aug 11, 2015 at 15:38
The same as Philippe Goutet's, but using the fp
module of LaTeX3; however the syntax of the \convertto
command is different:
\convertto{1in}{pt}
returns 72.26999
, just the number. With \convertto*{1in}{pt}
we'd get 72.26999pt
, with the unit.
\documentclass[a4paper]{article}
\usepackage{array}
\usepackage[hmargin=2cm]{geometry}
\usepackage{xparse}
\ExplSyntaxOn
\NewExpandableDocumentCommand{\convertto}{smm}
{
\egreg_convertto:nn {#2}{#3}
\IfBooleanT{#1}{#2}
}
\cs_new:Npn \egreg_convertto:nn #1 #2
{
\fp_eval:n { round( \dim_to_decimal:n { #1 } / \dim_to_decimal:n {1#2} , 5 ) }
}
\ExplSyntaxOff
\begin{document}
\begin{center}\begin{tabular}
{>{\def\colunit{pt}}l<{\convertto{1\colunit}{\rowunit}}
>{\def\colunit{mm}}l<{\convertto{1\colunit}{\rowunit}}
>{\def\colunit{cm}}l<{\convertto{1\colunit}{\rowunit}}
>{\def\colunit{ex}}l<{\convertto{1\colunit}{\rowunit}}
>{\def\colunit{em}}l<{\convertto{1\colunit}{\rowunit}}
>{\def\colunit{bp}}l<{\convertto{1\colunit}{\rowunit}}
>{\def\colunit{dd}}l<{\convertto{1\colunit}{\rowunit}}
>{\def\colunit{pc}}l<{\convertto{1\colunit}{\rowunit}}
>{\def\colunit{in}}l<{\convertto{1\colunit}{\rowunit}}
>{\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}
Both \convertto
and \convertto*
can be used in an expandable context.
The same table but with siunitx
(with the already built one for comparison). One needs to prepare the body of the table beforehand.
\documentclass[a4paper]{article}
\usepackage{siunitx,array}
\usepackage[hmargin=1cm]{geometry}
\usepackage{xparse}
\ExplSyntaxOn
\seq_new:N \g_egreg_convertto_units_seq
\seq_new:N \l_egreg_convertto_temp_seq
\tl_new:N \l_egreg_convertto_body_tl
\seq_gset_from_clist:Nn \g_egreg_convertto_units_seq
{
pt, mm, cm, ex, em, bp, dd, pc, in
}
\cs_new_protected:Nn \__egreg_convertto_maketable:
{
\seq_map_inline:Nn \g_egreg_convertto_units_seq
{
\seq_clear:N \l_egreg_convertto_temp_seq
\seq_map_inline:Nn \g_egreg_convertto_units_seq
{
\seq_put_right:Nx \l_egreg_convertto_temp_seq { \egreg_convertto:nn { 1####1 } { ##1 } }
}
\tl_put_right:Nx \l_egreg_convertto_body_tl
{
\seq_use:Nn \l_egreg_convertto_temp_seq { & } & \exp_not:n { \textbf{##1} \\ }
}
}
\seq_set_map:NNn \l_egreg_convertto_temp_seq \g_egreg_convertto_units_seq { {\exp_not:N \textbf{1\,##1}} }
}
\NewDocumentCommand{\maketable}{}
{
\__egreg_convertto_maketable:
\begin{tabular}{*{\seq_count:N \g_egreg_convertto_units_seq}{S[table-format=2.5]}l}
\seq_use:Nn \l_egreg_convertto_temp_seq { & } \\
\l_egreg_convertto_body_tl
\end{tabular}
}
\NewExpandableDocumentCommand{\convertto}{smm}
{
\egreg_convertto:nn {#2}{#3}
\IfBooleanT{#1}{#2}
}
\cs_new:Npn \egreg_convertto:nn #1 #2
{
\fp_eval:n { round( \dim_to_decimal:n { #1 } / \dim_to_decimal:n {1#2} , 5 ) }
}
\ExplSyntaxOff
\begin{document}
\begin{center}
\sisetup{group-digits=false}
\maketable
\end{center}
\begin{center}
\begin{tabular}
{>{\def\colunit{pt}}l<{\convertto{1\colunit}{\rowunit}}
>{\def\colunit{mm}}l<{\convertto{1\colunit}{\rowunit}}
>{\def\colunit{cm}}l<{\convertto{1\colunit}{\rowunit}}
>{\def\colunit{ex}}l<{\convertto{1\colunit}{\rowunit}}
>{\def\colunit{em}}l<{\convertto{1\colunit}{\rowunit}}
>{\def\colunit{bp}}l<{\convertto{1\colunit}{\rowunit}}
>{\def\colunit{dd}}l<{\convertto{1\colunit}{\rowunit}}
>{\def\colunit{pc}}l<{\convertto{1\colunit}{\rowunit}}
>{\def\colunit{in}}l<{\convertto{1\colunit}{\rowunit}}
>{\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}
-
It seems that TeX's memory you used is more important. For Philippe :777 strings out of 493481 10679 string characters out of 3140965 67406 words of memory out of 3000000 For you 7172 strings out of 493481 128969 string characters out of 3140965 174995 words of memory out of 3000000 May 9, 2013 at 8:16
-
1@AlainMatthes Loading
expl3
on top of LaTeX2e has a big impact. If I loadxparse
over Philippe's macros I get 7166 strings out of 493481, 128879 string characters out of 3140966, 175547 words of memory out of 3000000. LaTeX3 will surely consume more memory than LaTeX2e, at the advantage of a cleaner approach.– egregMay 9, 2013 at 8:52 -
@AlainMatthes There's a reason that the LaTeX3 approach didn't fly at all when it was first developed (early 1990s). As egreg says, there is a cost to having a more structured approach, but the idea is that you enhance code readability and logic.– Joseph Wright ♦May 10, 2013 at 6:50
-
Not sure what is happening. I copied the code for your answer into a MacTeX2016 (updated a few days ago) TeXShop file. The first row and first column are fine, but all other entries are incorrect. For example, Column 2 Row 2 is 8.09555 and Column 2 Row 9 is 205.62699. Did I neglect something?– sgmoyeMar 27, 2017 at 20:03
-
My posting just crossed the other ones. Best to view it, in action.
\documentclass[11pt]{article} % use larger type; default would be 10pt
\usepackage{xcolor}
\begin{document}
\newdimen\temp
\def\alength#1#2{
\temp#1
\nointerlineskip \baselineskip=2pt
\vbox{\hbox{\hskip-29pt\texttt{\textcolor{#2}{#1=\the\temp}}}
\hbox{\vtop{\color{#2}\hrule width 130pt\vspace{#1}\hrule width 130pt}}%
\vspace{0.9cm}}
}
\alength{1cm}{blue}
\alength{1pc}{red}
\alength{1mm}{orange}
\alength{1cc}{red}
\alength{1dd}{red}
\alength{100000sp}{purple}
\alength{1in}{black}
\alength{1bp}{brown}
\alength{1em}{black}
\alength{1ex}{black}
\end{document}
-
1It is better if you put all in one base line to make a comparison. Jan 4, 2011 at 17:26
-
@xport The base is the relationship to points! I tried to give something to visualize the length (with the exception of the sp, which is smaller than the visible wavelength and hence I scaled that by100K. Unit conversion tables are normally done like this. Jan 4, 2011 at 18:32
-
Thanks Yiannis Lazarides, but how to calc result in mm? 1pc=x mm 1pt=x mm 1ex=x mm 1em=x mm Jan 5, 2011 at 11:05
Some more examples with 1em
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{mathpazo}
\newsavebox\CBox
\newlength\Length \Length=1em
\begin{document}
\sbox\CBox{M}
\the\wd\CBox : \the\Length
\tiny\Length=1em
\sbox\CBox{M}
\the\wd\CBox : \the\Length
\Huge\Length=1em
\sbox\CBox{M}
\the\wd\CBox : \the\Length
\end{document}
As already mentioned in other answers, the e-TeX
\numexpr
and dimexpr
allow easy comparisons of dimensions, through conversions to integers. In particular applying \number
to a \dimexpr
expression returns the internal representation of the dimension in scaled points: there are 65536 scaled points in one pt. Using this we can see some funny effect of the internal truncations done by TeX
:
We see that 100bp
are represented in an exact manner internally (exact meaning that the ratio 72.27/72
is exactly verified). The next to last line should read rather 100bp/100pt
, and not 1bp/1pt
, to illustrate that this exact ratio is obtained only for dimensions which are integer multiples of 100bp
. As we can see indeed, it is not possible to represent exactly 10bp
as an integer number of sp
. We see that truncation, rather than rounding is used. Indeed 10bp
would be more accurately represented by 657818sp
and 1bp
would be more accurately equated to 65782sp
.
The code for producing the above:
1bp=\number\dimexpr 1bp\relax sp
10bp=\number\dimexpr 10bp\relax sp
100bp=\number\dimexpr 100bp\relax sp
1000bp=\number\dimexpr 1000bp\relax sp
10000bp=\number\dimexpr 10000bp\relax sp
1pt=\number\dimexpr 1pt\relax sp
10pt=\number\dimexpr 10pt\relax sp
100pt=\number\dimexpr 100pt\relax sp
1000pt=\number\dimexpr 1000pt\relax sp
10000pt=\number\dimexpr 10000pt\relax sp
\bye
The last lines were done with \input xintfrac.sty
(package xint ) and
1bp/1pt=\xintIrr{\number\dimexpr 100bp\relax/\number\dimexpr 100pt\relax }
72.27/72=\xintIrr{72.27/72}
\bye
To get the e-TeX
extensions the executable etex
(or pdftex
which is what I actually used) rather than tex
must be used.
I am not completely satisfied with the macro convertto
because I have no control over the number of digits after the decimal separator and I always have to use the decimal point as the decimal separator, as is common in the USA. In many other countries, however, the decimal comma is used, which is made possible by the siunitx package. My macro ConvertTo
has an optional parameter for the number of digits after the decimal separator and uses the package fp for calculation.
\documentclass{article}
\usepackage{fp}
\usepackage[locale = DE,detect-all]{siunitx}
\makeatletter
\def\convertto#1#2{\strip@pt\dimexpr #2*65536/\number\dimexpr 1#1}
\makeatother
\newcommand*\ConvertTo[3][2]{%
\FPdiv\res{\number\dimexpr #3}{\number\dimexpr 1#2}\relax%
\FPeval\res{round(\res:#1)}\SI\res{#2}}
\begin{document}
\newdimen\mylength\mylength=5440pt
\convertto{cm}{\mylength}\ cm, \ConvertTo{cm}{\mylength},
\ConvertTo[6]{cm}{\mylength}, \ConvertTo[0]{bp}{\mylength}.
\end{document}
Output: 191.19421 cm, 191,19 cm, 191,194 216 cm, 5420 bp.
Remark: If you're a pedantic mathematician like me, you'll notice that the result for cm is only correct up to the third digit after the decimal point. The next macro calculates more precisely, see my answer to How to print a length accurately and with user-controlled rounding?
\newcommand{\ScaledPointsInPoint}{\number \dimexpr 1pt \relax}
\newcommand*{\FPSizeCm}[2][2]{%
\FPdiv\res{\number\dimexpr #2\relax}{\ScaledPointsInPoint}%
\FPdiv\res{\res}{72.27}%
\FPmul\res{2.54}{\res}%
\FPeval\res{round(\res:#1)}%
\SI\res{\cm}}
This macro is more precise, because TeX obviously converts all lengths internally first into points and then into scaled points. So it is better to first convert back from scaled point to point and then to inch, cm, mm, etc. This is more accurate than converting directly into these units as the macros convertto
and ConvertTo
do.