Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

How to find the ratio of a length command (e.g., \textwidth) to a reference value (e.g., 6cm) ? Actually I want to use the ratio for the \scalebox argument, e.g., \scalebox{<ratio>}.

\documentclass{article}
\usepackage[showframe=true]{geometry}
\usepackage{pst-node}
\usepackage{graphicx}

\usepackage{fp}
\usepackage{pgf}
\pgfmathsetmacro{\ratio}{\the\textwidth/(6cm)}

\makeatletter
  \FPdiv\thecm{6}{2.54} %72.27
  \FPmul\thecminpoints{\thecm}{72.27}
  \FPdiv\thescale{\strip@pt\textwidth}{\thecminpoints}%
\makeatother

\begin{document}
\noindent%
%\scalebox{\thescale}{%
\scalebox{\ratio}{%
\begin{pspicture}(6,4)
\pnode(2,2){A}\psframe(A)
\pnode(4,2){B}\pscircle(B){2}
\end{pspicture}}
\uput[-135](A){$A$}
\rput(B){$B$}
\end{document}

alt text

share|improve this question
    
@Matthew, thanks for editing. :) –  xport Dec 2 '10 at 16:01
    
Could you just change \begin{pspicture}(6,4) to \begin{pspicture}(\textwidth) ? –  Will Robertson Dec 2 '10 at 16:57
    
@Will, you try it first :) –  xport Dec 3 '10 at 3:29
    
Oops; I did try it but I got a bit confused with what I was seeing with the output. Sorry for the noise. –  Will Robertson Dec 6 '10 at 1:29
    
No problem Will, it is fun! –  xport Dec 6 '10 at 2:14

5 Answers 5

up vote 6 down vote accepted

TeX can do 64-bit integer mul-divs; the resulting integer can be converted to a decimal number via the sp-to-pt conversion:

\documentclass{minimal}
\begin{document}
\makeatletter
\strip@pt\dimexpr\number\numexpr\number\textwidth*65536/\number\dimexpr6cm\relax\relax sp\relax
\end{document}

Or, more general:

\documentclass{minimal}
\makeatletter
\newcommand*{\DivideLengths}[2]{%
  \strip@pt\dimexpr\number\numexpr\number\dimexpr#1\relax*65536/\number\dimexpr#2\relax\relax sp\relax
}
\makeatother
\begin{document}
\DivideLengths{\textwidth - 0.2\textheight}{2cm + 4cm}
\end{document}
share|improve this answer
    
Thank Philipp, your code scares me. I am not familiar with plain tex. I don't know how to plug it into my problem. –  xport Dec 2 '10 at 16:53
1  
The \DivideLengths macro from the second snipped simply expands to a decimal representation of the ratio. –  Philipp Dec 2 '10 at 18:13
    
Good solution. –  Yiannis Lazarides Dec 2 '10 at 20:38
    
thanks. Could you help me to describe how to parse your macro step by step? I don't know how this macro works. What is the \number, \relax, etc for? –  xport Dec 3 '10 at 0:58

You can use \the\textwidth to give you the value of the dimension in points and you can use that to calculate the width in cm (in inch (1 in is 72.27 pt)).

You can automate all these with LaTeX calculations depending for what you need the calculations.

Edit

I would use the fp package for the calculations as follows:

\makeatletter
  \FPdiv\thecm{6}{2.54} %72.27
  \FPmul\thecminpoints{\thecm}{72.27}
  \FPdiv\thescale{\strip@pt\textwidth}{\thecminpoints}%
  \thescale
\makeatother

\scalebox{\thescale}{Test}
share|improve this answer
    
Thank Yiannis. Please see my first edit. :) –  xport Dec 2 '10 at 15:49
1  
@xport There might be shorter and more elegant ways to do it, but I would do it this way. Search for LaTeX3 calculations for other ways on this site. There was also question on strip@pt that explains how this strips the point. –  Yiannis Lazarides Dec 2 '10 at 16:12
    
Thank again Yiannis. Well done. But \thescale before \makeatother must be removed. –  xport Dec 2 '10 at 16:22
1  
@xport Sure, I put it there so one can see the result of the calculation, you can just comment it out. –  Yiannis Lazarides Dec 2 '10 at 20:31

TeX doesn't have a data type for decimal numbers and can't natively divide dimensions (for the mathematicians: TeX's dimensions form a one-dimensional vector space over the field of rational numbers, but not a field by themselves). You can use pgfmath to do it:

\documentclass{article}
\usepackage{pgf}
\begin{document}

\pgfmathsetmacro{\ratio}{\the\textwidth/(6cm)}
\scalebox{\ratio}{\fbox{stuff}}

\end{document}

But the confused questions and presumptive answers are saying that there might be a better way to get what you really want.

share|improve this answer
    
thanks. Your solution works. –  xport Dec 2 '10 at 16:41
1  
In fact, TeX dimensions are always integers, which can be multiplied and divided without any external package. –  Philipp Dec 2 '10 at 16:44
1  
@Phillipp: I'm confused. What is the smallest dimension then? –  Matthew Leingang Dec 2 '10 at 16:52
    
@Philipp: You are right! TeXbook, Chapter 10, p. 58 "TeX represents all dimensions as an integer multiple of the tiny units called sp" which is 1/65536 of a point. But you have still have to extract this multiple if you want to divide them, right? –  Matthew Leingang Dec 2 '10 at 17:16
1  
TeX does the division by 65536 when it has to print the decimal representation of a dimension. So generally you can use integer arithmetic, multiply by 65536 (before division to avoid rounding), have TeX treat the result as a dimension, convert that to the result string, and strip the unit suffix. –  Philipp Dec 2 '10 at 18:16

I think you probably want

\resizebox{0.5\textwidth}{!}{...}
share|improve this answer
    
I want \scalebox{\textwidth divided by 6 cm}{stuff} –  xport Dec 2 '10 at 15:55
    
@xport What on earth for? I'm up too late so I might have lost it, but this doesn't seem like a rational scaling factor for a box of unknown size. –  Will Robertson Dec 2 '10 at 16:36
    
@xport Given your latest edit what's wrong with replacing the \scalebox line by \resizebox{\textwidth}{!}{ ? –  Will Robertson Dec 2 '10 at 16:50
    
Sorry Will, it does not make sense. :) –  xport Dec 2 '10 at 16:58
    
@xport looking at this again for some reason, I have no idea what you mean. You're trying to make the box as wide as the page, right? So why not just tell TeX that's how large you want it (using \resizebox) instead of calculating the scale factor manually? –  Will Robertson May 19 '11 at 11:24

You can compute expandably (hence as argument to \scalebox) using xintfrac

circles

\documentclass{article}
\usepackage[showframe=true]{geometry}
\usepackage{pst-node}
\usepackage{graphicx}

\usepackage{xintfrac}

\begin{document}
\noindent
\scalebox{\xintRound {5}{\textwidth/\dimexpr 6cm\relax}}{%
\begin{pspicture}(6,4)
\pnode(2,2){A}\psframe(A)
\pnode(4,2){B}\pscircle(B){2}
\end{pspicture}}
\uput[-135](A){$A$}
\rput(B){$B$}
\end{document}

Further remarks:

  1. the first argument 5 to \xintRound is the number of digits to keep after the decimal mark for the output; the fraction is computed exactly before this rounding. Presence of a denominator is optional, \xintRound {4}{1.2345678} outputs 1.235 (oops) 1.2346.

  2. numerator and denominator involving arithmetic operations with +, *, - and parentheses (which will get executed automatically inside a \numexpr) should not have more than eight tokens (here the denominator has already five). For longer input use \the\numexpr <complicated stuff>\relax for the numerator or, respectively, the denominator.

  3. or, you can also load package xintexpr and have input such as \xintRound {5}{\xinttheexpr arbitrarily complicated expression \relax}. For example \xinttheexpr \LenA*\LenB*\LenC/((\LenD+\LenE)*(\LenF+\LenG))\relax will compute exactly without arithmetic overflow. Use then \xintRound to print it as fixed point number with the desired number of digits after decimal mark (if you want truncation rather than rounding, use \xintTrunc).

    3a. release 1.1 of xint will have the syntax \xinttheiexpr [4] ... \relax as a shortcut to \xintRound {4}{\xinttheexpr ... \relax}

  4. if the same computation has to be performed many times, just do it once in an \edef: \edef\RATIO{\xintRound{5}{<numerator>/<denominator>}}, and then use \RATIO wherever needed.

  5. if you want to use explicit dimensions such as 6cm or 1.2345in then put it in \dimexpr .. \relax and, if you are not using \xinttheexpr .. \relax and if these dimension specifications have many digits, you may need to embed in \the\numexpr .. \relax (see point 2 above). Within \xinttheexpr just use \dimexpr 1.2345in\relax.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.