9

The code

\documentclass{memoir}

\begin{document}
\fontsize{\dimexpr 1.2^{3} 10pt}{\dimexpr 1.2^{3} 10pt}\selectfont Hello TeXworld.
\end{document}

does not work. Why not?

EDIT: I need a solution that supports all integral (including negative) exponents.

5
  • 1
    Beyond 'this is not valid syntax for a \dimexpr' I'm not sure what you are after here as an answer! (See for example tex.stackexchange.com/questions/88344/…)
    – Joseph Wright
    Jan 21, 2015 at 9:00
  • Obviously, I would like someone to correct it to the right syntax. ;-)
    – Gaussler
    Jan 21, 2015 at 9:01
  • 1
    You can also check out the Expression section in texdoc etex, which says An expression consists of one or more terms of the same type to be added or subtracted; a term of type t consists of a factor of that type, optionally multiplied and/or divided by numeric factors; finally a factor of type t is either a parenthesized subexpression or a quantity (number, etc.) of that type. Jan 21, 2015 at 9:03
  • apart from dimexpr not having any syntax for power you don't have any multiplication symbol \dimexpr 1.2 10pt would not work either Jan 21, 2015 at 9:52
  • No, but from what I gathered by looking around, it seemed that the multiplication symbols was not used when multiplying lengths by non-integral numbers. Hence I hoped that the } in front would convince TeX that there was an implicit multiplication symbol in front. Can't say I ever really believed it would work, though.
    – Gaussler
    Jan 21, 2015 at 9:55

2 Answers 2

14

e-TeX's \dimexpr only allows a very limited range of items inside the expression. In particular, you can only multiply a dimension by an integer value

\dimexpr 10pt * 5\relax
\dimexpr 10pt * (5 * 5)\relax

Note the fact that the dimension here comes first. As is the case for a TeX register, you can multiply a \dimexpr by a real number by placing it before the expression

1.2\dimexpr 10pt * 5 \relax

Thus for your case you will need a series of expressions, each multiplied by 1.2, or to pre-calculate the factor

\dimexpr1.2\dimexpr1.2\dimexpr1.2\dimexpr 10pt \relax\relax\relax\relax
\dimexpr 1.728\dimexpr 10pt\relax

An alternative approach would be to use the expl3 FPU to do the floating point work, for example

\usepackage{expl3}
\ExplSyntaxOn
\cs_new_eq:NN \fpeval \fp_eval:n
\cs_new_eq:NN \fptodim \fp_to_dim:n 
\ExplSyntaxOff

then one of

\dimexpr\fpeval{1.2^(3)}\dimexpr 10pt\relax
\dimexpr\fptodim{1.2^(3) * 10}\relax

where the latter uses the fact that the conversion of a float to dimen uses points as the unit. Note that this method supports negative exponents:

\the\dimexpr\fpeval{1.2^(-3)}\dimexpr 10pt\relax % => 5.78703pt
\the\dimexpr\fptodim{1.2^(-3) * 10}\relax        % => 5.78703pt
4
  • Is \cs_new_eq:NN the recommended way of populating Expl macros?
    – yo'
    Jan 21, 2015 at 9:15
  • @yo' You could use \DeclareExpandableDocumentCommand{\fpeval}{m}{\fp_eval:n{#1}}
    – egreg
    Jan 21, 2015 at 9:17
  • @yo' For the case here of creating a couple of expandable document commands which are equivalent to expl3 code level ones there is not much in it between this and \DeclareExpandableDocumentCommand.
    – Joseph Wright
    Jan 21, 2015 at 9:17
  • Yes, I know it supports negative exponents. Excellent answer, by the way! I'm currently using your answer. But it never hurts to get David's answer to work for the purpose as well. I plan to keep the acceptance of your answer anyway.
    – Gaussler
    Jan 21, 2015 at 11:39
9

You need to encode powers as a macro but a simple recursive loop should do the trick

+ve

===: \dimexpr 1.2\dimexpr 1.2\dimexpr 1.2\dimexpr 10pt\relax \relax \relax \relax 
===: 17.27985pt

-ve

===: \dimexpr \dimexpr (\dimexpr (\dimexpr (10pt * 100)/120 \relax  * 100)/120 
\relax  * 100)/120 \relax \relax 
===: 5.78703pt

Log output from

\documentclass{memoir}

\def\powerfactor#1#2#3{%
\ifnum#2=0
\dimexpr#3\expandafter\relax
\else
\afterfi
\powerfactor{#1}{\numexpr#2-1\relax}{#1\dimexpr#3\relax}%
\fi}
\def\afterfi#1\fi{\fi#1}

\def\negpowerfactor#1#2#3{%
\ifnum#2=0
\dimexpr#3\expandafter\relax
\else
\afterfi
\negpowerfactor{#1}{\numexpr#2-1\relax}{\dimexpr(#3 * 100)/\twodp#100.{}{}! \relax}%
\fi}
\def\twodp#1.#2#3#4!{#1#2#3}

\typeout{===: \powerfactor{1.2}{3}{10pt}}
\typeout{===: \the\powerfactor{1.2}{3}{10pt}}
\typeout{===: \negpowerfactor{1.2}{3}{10pt}}
\typeout{===: \the\negpowerfactor{1.2}{3}{10pt}}

\begin{document}

{\fontsize{\powerfactor{1.2}{3}{10pt}}{\powerfactor{1.2}{3}{10pt}}\selectfont Hello TeXworld.\par}

{\fontsize{\negpowerfactor{1.2}{3}{10pt}}{\powerfactor{1.2}{3}{10pt}}\selectfont Hello TeXworld.\par}

\end{document}
6
  • Brilliant answer! The only thing is (and I should have said this in the first place) I also want negative (but still integral!) exponents. Is this possible?
    – Gaussler
    Jan 21, 2015 at 11:33
  • 1
    @Gaussler yes you just have to spot the negative value (otherwise recursing by subtracting one until you get to 0 may take a while) and code it as repeated division. Exercise for the reader?:-) Jan 21, 2015 at 12:36
  • Yes, I guessed as much. I was mostly concerned about breaking your fancy \afterfi method. But it worked out just fine. :-)
    – Gaussler
    Jan 21, 2015 at 12:46
  • 1
    @Gaussler \dimexpr 10pt * 10 / 12 \relax Jan 21, 2015 at 15:41
  • 1
    @Gaussler updated with negative powers Jan 22, 2015 at 0:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .