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 01 '13 at 03: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 01 '13 at 03: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 01 '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 [tag: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 01 '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 01 '13 at 23:20
  • 1) PGF routines? You can use PGFmath without PGF (but not vice versa). Of course, you can use fp or other math-related packages. 2) Yes, usually, some form of macro is used because it can be “protected” from the user level by using @ in its name. Nearly every character can do apart from 0-9., the space is a little bit too special for this and can cause troubles. PGFmath uses \pgfmath@stop. (And, indeed, its int function is defined as \def\pgfmathint@@#1.#2\pgfmath@stop, frac works similar but also must deal with integer input.) – Qrrbrbirlbel Nov 01 '13 at 23:26
  • I've clarified this question as a pgfmath only question and have moved other issues to separate questions. – Geoff Pointer Nov 04 '13 at 00:46

1 Answers1

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

egreg
  • 1,121,712
  • 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 04 '13 at 00: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 05 '13 at 00:55
  • @GeoffPointer Done. – egreg Nov 05 '13 at 10:17