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.

  • 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 '15 at 9:00
  • Obviously, I would like someone to correct it to the right syntax. ;-) – Gaussler Jan 21 '15 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. – TonioElGringo Jan 21 '15 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 – David Carlisle Jan 21 '15 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 '15 at 9:55
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
| improve this answer | |
  • Is \cs_new_eq:NN the recommended way of populating Expl macros? – yo' Jan 21 '15 at 9:15
  • @yo' You could use \DeclareExpandableDocumentCommand{\fpeval}{m}{\fp_eval:n{#1}} – egreg Jan 21 '15 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 '15 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 '15 at 11:39
8

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}
| improve this answer | |
  • 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 '15 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?:-) – David Carlisle Jan 21 '15 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 '15 at 12:46
  • 1
    @Gaussler \dimexpr 10pt * 10 / 12 \relax – David Carlisle Jan 21 '15 at 15:41
  • 1
    @Gaussler updated with negative powers – David Carlisle Jan 22 '15 at 0:06

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.