11

Example:

\documentclass{article}
\begin{document}

\newlength{\picwidth}

\setlength{\unitlength}{1bp}
\settowidth{\picwidth}{\begin{picture}(10,10)\end{picture}}
\typeout{width: \the\picwidth}

\settowidth{\picwidth}{\rule{10bp}{0pt}}
\typeout{width: \the\picwidth}

\end{document}

Output in the log:

width: 10.03738pt
width: 10.03749pt

I'm expecting the two lines to be the same.

3 Answers3

12

This is due to rounding errors. You can clearly see it if you convert the lengths to integer numbers, which shows the thing TeX core actually stores:

\documentclass{article}
\begin{document}

\newlength\lena
\newlength\lenb
\newlength\lenc

\setlength{\lena}{1bp}     % 1bp
\setlength{\lenb}{10\lena} % 10*1bp
\setlength{\lenc}{10bp}    % 10bp

\typeout{a: \the\lena} % 1.00374pt
\typeout{b: \the\lenb} % 10.03738pt
\typeout{c: \the\lenc} % 10.03749pt

\typeout{a: \number\lena} % 65781
\typeout{b: \number\lenb} % 657810
\typeout{c: \number\lenc} % 657817

\end{document}
yo'
  • 51,322
  • @tochecz ... and \numexpr \lena\relax works too, if you need the value (as an integral number of sp's) in an \ifnum test (but to get its explicit representation, one again needs a prefix then, either \the or \number which both give now the same thing). –  Feb 02 '14 at 22:44
12

To add a little to tochecz's answer: in terms of the smallest dimension unit manipulated by TeX, the sp, 1/65536 of a pt, a dimension with d bp units has exact value (1644544/25)*d sp units. TeX will truncate this to an integer number of sp units. When you multiply by 10 a dimension you actually multiply by 10 its representation as an integral number of sp units. When you however express directly a dimension as for example 10bp then floor((1644544/25)*10) is evaluated.

Thus 1bp is floor(1644544/25), that is 65781 sp units. Then 10*1bp is 657810 sp units.

But 10bp is floor(16445440/25)=657817 sp units.

And 100bp is floor(164454400/25)=6578176 sp units (hence exactly represented). The only exactly represented dimensions expressed as an integral number of bp units are those multiple of 25bp.

9

The reason for the differences has been explained elsewhere. If it's critical that the dimension is as exact as possible, you can load the picture package that allows one to express dimensions with their unit of measure in the picture environment.

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

\newlength{\picwidth}

\settowidth{\picwidth}{\begin{picture}(10bp,10bp)\end{picture}}
\typeout{width: \the\picwidth}

\settowidth{\picwidth}{\rule{10bp}{0pt}}
\typeout{width: \the\picwidth}

\end{document}

The output on the terminal is

width: 10.03749pt
width: 10.03749pt
egreg
  • 1,121,712
  • Surprisingly, the original picture environment accepts only integers, (dimensions being then multiple of \unitlength) but the primitive \number is, to the best of my knowledge, nowhere mentioned in Lamport's book although it is very convenient when one sets \unitlength to be 1sp. –  Feb 02 '14 at 22:42
  • @jfbu It's good \number is not mentioned, as it has a syntax foreign to LaTeX. – egreg Feb 02 '14 at 22:46
  • My feeling is that LaTeX's syntax is not that perfect that it should forbid using TeX's primitives! what then about \numexpr and \dimexpr? (from e-TeX) –  Feb 02 '14 at 22:48
  • 2
    @jfbu \numexpr and \dimexpr came well after Lamport's manual. – egreg Feb 02 '14 at 22:49
  • yes, my point: at the time of Lamport's manual, \number was the only way to expandably get the exact value of a dimension. Furthermore, the picture environment required integers, but \the on a dimension gives a decimal number of pt's. –  Feb 02 '14 at 22:51