6

I would like to write a macro getlengthin to get a length or dimen as floating point number in a specified unit. Here is what I have created so far:

\documentclass{article}

\usepackage[nomessages]{fp}

\newcount\lengthcount
\newcount\unitcount
\def\getlengthin#1#2{%
    \lengthcount=#1%
    \unitcount=\dimexpr1#2%
    \FPdiv\result{\the\lengthcount}{\the\unitcount}%
    \result%
}

\def\a{\getlengthin{\paperwidth}{mm}} % \edef does not work here !

\begin{document}

    \a

    \getlengthin{\paperwidth}{mm}

    \getlengthin{\textheight}{mm}

\end{document}

For some reason I need to calculate the length in the preamble and I tried to use edef, but edef does not work with my macro. What is the problem here?

5

A modification of my answer at https://tex.stackexchange.com/a/213027/4427

\documentclass{article}

\usepackage{xparse,siunitx}

\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\convertdim}{O{2}mm}
 {
  \fp_eval:n { round ( \dim_to_decimal_in_unit:nn { #2 } { 1#3 } , #1 ) }
 }
\ExplSyntaxOff

\NewDocumentCommand{\getlengthin}{O{2}mm}
 {%
  \SI[round-mode=places,round-precision=#1]{\convertdim{#2}{#3}}{#3}%
 }

\begin{document}

\convertdim{\paperwidth}{pt} -- \getlengthin{\paperwidth}{pt}

\convertdim[5]{\paperwidth}{in} -- \getlengthin[5]{\paperwidth}{in}

\convertdim[3]{\paperwidth}{cm} -- \getlengthin[3]{\paperwidth}{cm}

\end{document}

For both commands the optional argument is the number of digits for the rounding.

The first command is fully expandable, so it can be used in other contexts where a decimal number is needed.

enter image description here

See also the lengthconvert package.

  • Thank you very much. Your convertdim command does the job. – Patrick S Jan 9 '15 at 19:43
3

Here's a way to do this:

8.50 in
193.30 mm
19.3 cm

\documentclass{article}

\usepackage{siunitx}
\ExplSyntaxOn
  \cs_new_eq:NN \calc \fp_eval:n
\ExplSyntaxOff

\makeatletter
\newcommand{\getlengthin}[3][]{%
  \setlength{\@tempdima}{#2}% Capture length
  \setlength{\@tempdimb}{1 #3}% Capture unit
  \SI[round-mode=places,round-precision=2,#1]
    {\calc{\strip@pt\@tempdima/\strip@pt\@tempdimb}}{#3}% Divide length by unit
}
\makeatother

\begin{document}

\getlengthin{\paperwidth}{in}

\getlengthin{\textheight}{mm}

\getlengthin[round-precision=1]{\textheight}{cm}

\end{document}

\getlengthin[<options>]{<length>}{<unit>} takes additional <options> from siunitx.


If you wish to perform conversions between lengths without really printing them, you can set them directly without problem:

\setlength{<length register>}{<length in whatever unit you want>}

So, for example, \setlength{\mylen}{12in} will set \mylen to 12 inches, but internally convert it to points (something you don't have to worry about). Or, \setlength{\mylen}{\dimexpr 3cm+2in-5pt+3bp-1mm} if you want an expression containing multiple units of measure.

  • Thanks for your answer, but unfortunately my problem is not completely solved yet: I need to calculate the length in the preamble, but when I add \edef\a{\getlengthin{\paperwidth}{in}} after makeatother and \a after \begin{document} I still get an error. – Patrick S Jan 9 '15 at 19:08
  • @PatrickS: If you just want to "calculate the length in the preamble", then you don't need to use a conversion. Set them using \setlength{<length register>}{<length in whatever measurement>}. – Werner Jan 9 '15 at 19:40
  • "Calculate the length" was not the right term, I am rather trying to "read" the length in a specific unit in the preamble. The convertdim command from egreg's answer did the job. Anyway, thank you for your help. – Patrick S Jan 9 '15 at 19:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.