8

Note: Firstly my apologies for making this confusing to start with. I have finally clarified matters I hope. This particular question is asking for macros that will split pgfmath results. The ones initially provided by egreg do just that. I am asking this question in a more general context elsewhere.

I know how to do this in c++, it's easy, but it's not so clear how to do it in LaTeX. In this case I'm working with 'pgfplots' so I have access to the pgfmath routines and thus I don't have to worry about how to remove the pt as they do it for me already.

I want the whole digits with no trailing "." or ".0" and I want the fraction digits with no preceding "0.".

The following MWE shows my failed attempts at doing this.

Output:

MWE Output

Code:

\documentclass[12pt]{article}
\usepackage[a5paper,margin=14mm]{geometry}

\usepackage{pgfplots}

\pgfplotsset{compat=1.9, /pgf/declare function={F(\x)=(\x+5)*(\x-1)*(\x-5);}}

\newlength{\printvar}

\newcommand{\intprint}[1]{\pgfmathparse{int(#1)}\pgfmathresult}
\newcommand{\fracprint}[1]{\pgfmathparse{frac(#1)}\pgfmathresult}

\newcommand{\truncprint}[1]{\pgfmathtruncatemacro{\printvar}{#1}\pgfmathprint{\printvar}}
\newcommand{\diffprint}[1]{\pgfmathtruncatemacro{\printvar}{#1}\pgfmathprint{#1-\printvar}}

\begin{document}
\par PGFMathParse F(1.5): \pgfmathparse{F(1.5)}\pgfmathresult
\par TruncPrint: \truncprint{F(1.5)}\quad DiffPrint \diffprint{F(1.5)}
\par IntPrint: \intprint{F(1.5)}\quad FracPrint \fracprint{F(1.5)}
\end{document}
  • 2
    The pgfplotstable package supports aligning numbers at their decimal separator. So does siunitx. Anyway, the easiest thing to separate int and frac part is using a delimited macro as in \def\myMacro#1.#2\myEnd{And then you can use #1 (int) and #2 (frac).}. (Something along those lines is used by PGFmath.) If you want to use that with lengths, you will need to remove the pt from \the which is already explained on TeX.sx. PGF also defines a few of those macros (\pgf@sys@tonumber, \Pgf@geT). – Qrrbrbirlbel Nov 1 '13 at 3:19
  • See also Stripping the pt from a dimension By the way, PGFmath already defines \pgfmathprint which does the same as your \numprint. – Qrrbrbirlbel Nov 1 '13 at 3:32
  • I kind of have an answer but let me ask first. Do you want a completely package independent answer or can it depend on others? Such as the ones Qrrbrbirlbel(man that's a drag to type that) mentioned. – percusse Nov 1 '13 at 20:25
  • 1
    @GeoffPointer I wouldn’t use a space to delimit the stripping macros, this can be gobbled or something (I don’t know how this interact with a \par). In the case of \pgfmathresult, this is an expansion problem, you will need to use \expandafter\printplainbefore\pgfmathresult (and here you won’t have the space you need). By the way, are you aware that pgfplots only uses PGFmath via TikZ via PGF? In your last case, you should be able to say simply \usepackage{pgfmath} instead of loading pgfplots. – Qrrbrbirlbel Nov 1 '13 at 22:50
  • @Qrrbrbirlbel (1) I'm currently happy with a solution using pgf because I'm doing a lot of work in pgplots with axis environments which is why I \usepackage{pgfplots}. None the less, I would ideally like a solution that doesn't use any `pgf' routines. (2) I tried your suggestion and it worked, but what do you recommend as suitable delimiter. I just used the letter m so I could try it out, but it looks ridiculous. But I guess you meant by \MyEnd, a macro that looks better in use and it doesn't matter too much what it actually is? – Geoff Pointer Nov 1 '13 at 23:20
10

When you do

\pgfmathparse{sqrt(2)}\printplainbefore\pgfmathresult.777

TeX follows instructions. It places 1.41421 as the replacement text of \pgfmathresult and proceeds expanding \printplainbefore; based on its definition, the first argument is \pgfmathresult and the second argument is .777 as shown by TeX when setting \tracingmacros=1:

\pgfmathresult ->1.41421

\printplainbefore #1.#2 ->#1
#1<-\pgfmathresult
#2<-777

So you get 1.41421 as the result. Remember that TeX never expands tokens when it's absorbing arguments. If you do

\pgfmathparse{sqrt(2)}\expandafter\printplainbefore\pgfmathresult

you get an error, because of how you decided to delimit the second argument. Using a space as the final delimiter is usually a very bad choice.

Here's how one could do, assuming that the argument of \printplainbefore is always an explicit number or a control sequence expanding thereto:

\makeatletter
\def\printplainbefore#1{\expandafter\@printplainbefore#1..\@nil}
\def\@printplainbefore#1.#2.#3\@nil{#1}
\def\printplainafter#1{\expandafter\@printplainafter#1..\@nil}
\def\@printplainafter#1.#2.#3\@nil{#2}
\makeatother

Complete example:

\documentclass[12pt]{article}
\usepackage[a5paper,margin=14mm]{geometry}

\usepackage{pgfplots}
\pgfplotsset{compat=1.9}

\makeatletter
\def\printplainbefore#1{\expandafter\@printplainbefore#1..\@nil}
\def\@printplainbefore#1.#2.#3\@nil{#1}
\def\printplainafter#1{\expandafter\@printplainafter#1..\@nil}
\def\@printplainafter#1.#2.#3\@nil{#2}
\makeatother

\begin{document}

\printplainbefore{1.41421} -- \printplainafter{1.41421}

\pgfmathparse{sqrt(2)}
\printplainbefore{\pgfmathresult} -- \printplainafter{\pgfmathresult}

\printplainbefore{1} -- \printplainafter{1}

\printplainbefore{.1} -- \printplainafter{.1}

\printplainbefore{0.1} -- \printplainafter{0.1}

\end{document}

You may want to add checks whether one of the two parts is empty, deciding to print 0 in this case.

enter image description here

  • This is a very instructive solution. Not only does it split my numbers, it's robust against input with missing bits, which saves a lot of my follow up questions. It taught me some important lessons about writing macros just when I was ready to learn them. Cheers – Geoff Pointer Nov 4 '13 at 0:47
  • I received no notification that you had added this second more general solution. I have simplified this question so that it fits with your first answer which works with \pgfmathresult. If you look at the OP now, it and my MWE, are much more straightforward. Would you mind moving your second answer to here? – Geoff Pointer Nov 5 '13 at 0:55
  • @GeoffPointer Done. – egreg Nov 5 '13 at 10:17

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.