[pstricks] Suggestions for \psPrintValue

Michael Sharpe msharpe at ucsd.edu
Mon Apr 27 04:15:25 CEST 2009

On Apr 26, 2009, at 1:42 PM, Buddy Ledger wrote:

>> Buddy, it's a good idea! But there is one thing left. When usind
>> descimals=2 you should always get two decimals 12.799344 -> 12.80,
>> but your solution gives 12.8. However, I changed the code to take the
>> comma and algebraic option into account.
> Herbert,
> That is great! Thanks.
> I've been trying to incorporate another option, where horizontal space
> can be preserved to create compound objects without the need for  
> manual
> makebox{} commands.  My attempts have been unsuccessful, but I think  
> it
> is possible.  knowing \psk at decimals and \psk at fontscale we should be  
> able
> to calculate the space required for the \psPrintValue object.  For
> scientific notation the character space required is roughly
> 3+\psk at decimals+floor(log(expon))+1 and for regular numbers
> floor(log(#))+\psk at decimals (FP package crashed on me when trying
> this).  This could also be done with count registers if you could read
> an input value one character at a time and test for decimal point or  
> "E"
> along the way (I don't know how to do this).
> The motivation here is to allow \psPrintValue to mesh properly with  
> text
> or other \psPrintValue objects.  I've included an example of my failed
> attempt at a generic solution.  As well I have included another  
> routine
> which demontrates what I want to be able to achieve, this routine is
> very specific and would have to be re-written to achieve different
> output, whereas if a space preservation option was possible within
> \psPrintValue generic objects could be created using the basic
> \psPrintValue routine.

You might get some ideas from the appended file, which gives a way to  
round a number given in either conventional form or in formats like  
1.23E-04 or -12.34e005, to a fixed number of decimal places. It works  
entirely at the TeX level, so there is no need to call \psPrintValue  
unless you have a number that is the result of a Postscript  
computation. This is not a completed package---the handling of the  
case where \decplaces<0 in not yet finished. Also, the size of numbers  
handled is limited. The string of output digits, not counting the  
period and sign, must be no more than 2^{31}, as it is stored in a  
single count register, unlike the fp package. The other thing is that  
\decplaces should have been handled as a keyword. See the end of the  
file for usage and test examples.


\newcount\my at cnta
\newcount\my at cntb
\newcount\my at cntc
\newcount\my at cntn
\newcount\my at cntx
\newcount\my at cnty
\newcount\my at cntz
\newif\if at period
\newif\if at anE
\newif\if at neg
\def\hasnegsign#1-#2\@nil{%check if expression contains .--call with  
% Check for value of \my at cntz to determine if exponent present
\ifx\@tmpB\@empty\@negfalse \else %
%remove neg from end of \@tmpB
\expandafter\removeneg\@tmpB %
\def\hasperiod#1.#2\@nil{%check if expression contains .--call with  
% Check for value of \my at cntz to determine if exponent present
\ifx\@tmpB\@empty\@periodfalse \else %
%remove period from end of \@tmpB
\expandafter\removeper\@tmpB %
\def\hasanE#1E#2\@nil{%check if expression contains an E--call with  
\ifx\@tmpB\@empty %try lower case
   \expandafter\hasane\@tmpA e\@nil %
   \ifx\@tmpB\@empty \@anEfalse %
   \else %
     \@anEtrue %
     \expandafter\removee\@tmpB %
   \fi %
\else %
   %remove E from end of \@tmpB
   \expandafter\removeE\@tmpB %
\def\hasane#1e#2\@nil{%check if expression contains an e--call with  

\def\get at length#1#2\@nil{%
\def\@@tmp{#2}\ifx#1\@empty\else\advance\my at cntx by\@ne \ifx\@@tmp 
\@empty\else\get at length#2\@nil \fi\fi %
\my at cntn=0 %
\hasanE#1E\@nil %checks if e/E format
\if at anE %\mantissa in \@tmpA, exponent in \@tmpB
   \my at cntn=\@tmpB \fi%
\expandafter\hasnegsign\@tmpA-\@nil %set \@negtrue if neg, abs val in  
\expandafter\hasperiod\@tmpA.\@nil %
\my at cntx=0 %
\ifx\@tmpA\@empty\my at cntx=\z@ \else\expandafter\get at length\@tmpA\@nil  
\my at cntz=\my at cntx %length of pre-.
\my at cntx=0 %
\ifx\@tmpB\@empty\my at cntx=\z@ \else\expandafter\get at length\@tmpB\@nil  
\my at cnty=\my at cntx %length of post-.
\ifnum\my at cntn=0 % do nothing
\else %
   \advance\my at cntx\my at cntz %total length
   \advance\my at cnty by-\my at cntn %
   \advance\my at cntz\my at cntn %new length of pre-.
   \ifnum\my at cntz<\z@ %
     \advance\my at cntx by -\my at cntz %
     \let\@tmpA\@empty %
     \loop\edef\@tmpB{0\@tmpB}\advance\my at cntz\@ne %
      \ifnum\my at cntz<\z@ \repeat % cntz=0 at end of loop
      \my at cnty=\my at cntx %
   \else %
     \ifnum\my at cntz>\my at cntx %
       \let\@tmpB\@empty %
       \my at cnty=\z@ %
       \my at cnta=\my at cntz %
       \loop\edef\@tmpA{\@tmpA0}\advance\my at cnta\m at ne %
        \ifnum\my at cnta>\my at cntx \repeat %
     \else %period is somewhere inside string
       \@splitstring{\@nxtB}{\my at cntz}
       \let\@tmpA\@nxtA %
       \let\@tmpB\@nxtB %
     \fi %
   \fi %
\fi %
\my at cnta=\decplaces \relax%
\ifnum\my at cnta<0 %leave as is
   \ifnum\my at cnty<\decplaces \relax%
     \loop\edef\@tmpB{\@tmpB0}\advance\my at cnty\@ne %
     \ifnum\my at cnty<\my at cnta\repeat %
\else % rounding code
    \ifnum\my at cnty>\decplaces \relax%round off \@tmpB
   \let\my at tempa\@empty %
   \edef\@nxtB{\@tmpA\@tmpB} %
    \my at cntb=\my at cntz \advance\my at cntb\decplaces \relax%
   \@splitstring{\@nxtB}{\my at cntb}%
   \ifx\@nxtA\@empty\my at cnta=0 \else\my at cnta=\@nxtA \fi%
   \expandafter\nextchar\@nxtB\@nil %
   \my at cntc=\@nxtA \relax%first digit in what's cut off
   \ifnum\my at cntc >4\relax \advance\my at cnta\@ne \fi %
   \edef\@nxtB{\the\my at cnta}%
    \my at cntx=\z@ %
    \expandafter\get at length\@nxtB\@nil %
    \ifnum\my at cntx<\decplaces\relax %
      \loop\edef\@nxtB{0\@nxtB}\advance\my at cntx\@ne \ifnum\my at cntx< 
\decplaces\relax\repeat \fi%
     \my at cntz=\my at cntx \advance\my at cntz -\decplaces\relax%
     \@splitstring{\@nxtB}{\my at cntz}%
\fi \fi \fi %
\my at cnta=\decplaces \relax%
\ifx\@tmpA\@empty \edef\@tmpA{0}\fi %
\edef\@tmpA{\if at neg-\fi \@tmpA}%
\ifnum\my at cnta<0\relax%
\else %
   \ifnum\my at cnta=\z@ %
     \@tmpA %
   \else %
     \@tmpA.\@tmpB %
\fi\fi %
\def\@splitstring#1#2{%#1=string, #2=position to split at
%results returned in \@nxtA, \@nxtB, no padding
\my at cntb=#2 %
\let\@nxtA\@empty %
\let\my at tempa\@empty %
\ifnum\my at cntb>\z@ %
\loop\expandafter\nextchar\@nxtB\@nil \edef\my at tempa{\my at tempa\@nxtA} 
\advance\my at cntb\m at ne\ifnum\my at cntb>0\repeat %
\let\@nxtA\my at tempa \fi}%
Test \verb|\fmtnum| macro

Unformatted & Formatted\\\hline
12E-02 & \fmtnum{12E-02}\\
-12e04 & \fmtnum{-12e04}\\
-127.415 & \fmtnum{-127.415}\\
99.995 & \fmtnum{99.995}\\
.01267 & \fmtnum{.01267}\\
1.267E-02 & \fmtnum{1.267E-02}\\
-12.6 &\def\decplaces{0} \fmtnum{-12.6}\\
123456789.60 &\def\decplaces{0}  \fmtnum{123456789.60}\\\hline


More information about the PSTricks mailing list