% This is nrrange.sty, a LaTeX package. % Christopher von B\"ulow, 2010.10.06 % Contains an algorithm to print out number ranges (aka "inclusive" or % "continuing numbers"), e.g. page ranges, in abbreviated form, % as suggested by various English style manuals. % My names for various abbreviation conventions/styles: % - "Oxford": The Oxford Guide to Style (2002, p. 169), % - "Chicago": The Chicago Manual of Style (15th edn 2003, p. 396), % - "MLA": MLA Style Manual and Guide to Scholarly Publishing % (2nd edn 1998, p. 118; MLA: Modern Language Association), % - "Cenglish": my style for English texts (almost Oxford), % - "Cgerman": my style for German texts, % - "shortest": leave out every redundant digit in the 2nd number % (one might also call this "minimal"), % - "full": leave out nothing, i.e. write out the 2nd number in full % (could also be called "longest", "maximal" or "trivial"). % These names should one day become alternative OPTIONS for the % nrrange package. % Which abbreviation convention is to be used depends on the style % manual you consult, or on the house style of your publisher. % One abbreviation convention would be the following, my hybrid between % Oxford and Chicago: % \numberrange{604}{609} -> "604--9" instead of "604--609", % whereas \numberrange{600}{609} -> "600--609" (Chicago, not Oxford) % [Oxf.: \numberrange{600}{609} -> "600--9"]; % \numberrange{623}{628} -> "623--8" (Oxford, not Chicago) % [Chic.: \numberrange{623}{628} -> "623--28"], % whereas \numberrange{613}{618} -> "613--18" (both Oxf. and Chic.). % I haven't seen any rationales for the conventions suggested by the % different style manuals, so I made up one of my own. The abbreviation % used should facilitate reading by leaving out redundant information, % as long as this doesn't confuse the reader. So, imagine your % (unabbreviated) number range as it would be spoken, e.g. "604--609" as % "[from] six hundred [and] four to six hundred [and] nine". In the % reader's mind this is digested (I suppose) as "in the 600's, go from 4 % to 9", which implies that you don't need to repeat the "600's" % information in the 2nd number word. In short, with the omissible part % put in parentheses: % "six hundred [and] four -- (six hundred [and]) nine". % The range "600--609", on the other hand, is spoken as "[from] % six hundred to six hundred [and] nine" and NOT digested (I believe) as % "in the 600's, go from 0 to 9", because the zero is not spoken. So, % if you omit the "six hundred", it sounds like "GO DOWN from 600 to 9", % or like it might be a reference to a figure/table 9 on p. 600. In % other words, "600--609" is NOT to be understood as % "six hundred -- (six hundred [and]) nine" % (i.e. the part in parentheses is NOT omissible), because there is no % expression on the left-hand side (no "zero") that would correspond to % the "nine" on the right-hand side. So you should repeat the "600's" % information: "600--609". % Similarly with the two ranges "623--628" and "613--618": The former is % of the form % "six hundred twenty-three -- (six hundred twenty-) eight", % where you can omit the "620"-part, somewhat like in "speakers of % English and (speakers of) German" or in "bicycle-(riders) and % tricycle-riders". The range "613--618", on the other hand, is NOT to % be understood as % "six hundred thirteen -- (six hundred) four (teen)", % because the part that is, strictly, redundant ("61x") does not form % a continuous phrase. (In Japanese, it would; number words there go % something like "six-hundred ten three to six-hundred ten four", like % for 20's, 30's etc. in English.) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \RequirePackage{ifthen,calc,refcount} % Some number variables for later use: \newcounter{power@fTen}% The power of 10 that corresponds % to the position of the digit we are currently investigating; % thus 100 is the power of 10 that, in 789, corresponds to the % position of digit 7, because there the "7" means "7 times 100". \newcounter{firstdigit@fm}% To memorize the first digit of m, \newcounter{firstdigit@fn}% resp. of n, after having calculated them. \newcounter{firstdigit@fmfollowedbyzeroes} \newcounter{higherp@wer} \newcounter{new@m} \newcounter{new@n} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newcommand{\pagerange}[2]% Takes two \label-keys as arguments. {\refused{#1}\refused{#2}% In case a reference is (as yet) undefined. % Apply \numberrange to the numbers \pageref delivers for the keys: pp.\ \numberrange{\getpagerefnumber{#1}}{\getpagerefnumber{#2}}% } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newcommand{\numberrange}[2] {% We presuppose that the two arguments, #1 =: M and #2 =: N, are % numbers. If M isn't less than N, we stop right there: \ifthenelse{\NOT #1 < #2} {#1--#2% An additional warning sign in the document would be nice. \typeout{The arguments for the numberrange command are wrong: either #1 and #2 are not both (just) numbers, or #1 is not less than #2.}% } % In the else-part, M < N is now assured. {% [1] % Write down M and the dash: #1--% % How many digits does M have? Calculate the power of 10 that % corresponds to the first ("highest") digit of M! % M is certainly greater-or-equal 10^0 (= 1): \setcounter{power@fTen}{1}% % In the following \whiledo-loop, power@fTen is certainly always % less-or-equal M. So we multiply power@fTen with 10, % obtaining higherp@wer, and try out higherp@wer as the new % power@fTen, until we have found the greatest power@fTen % less-or-equal M, i.e. the one such that M < higherp@wer. \setcounter{higherp@wer}{\value{power@fTen}*10}% \whiledo{\NOT #1 < \value{higherp@wer}} {\setcounter{power@fTen}{\value{higherp@wer}}% \setcounter{higherp@wer}{\value{power@fTen}*10}% }% % Now M is still greater-or-equal power@fTen, but less than % higherp@wer. The following command then works out recursively % which part of N to write down. \write@llorlosetheleadingdigit{#1}{#2}% }% [1] }% End of \newcommand{\numberrange} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newcommand{\write@llorlosetheleadingdigit}[2]% Depending on what #1 % (=: m) is: either write all of #2 =: n and stop; or lose the first % digit of m and of n, and then repeat that process with the new, % shortened m and n. {% If n has more digits than m (i.e. is greater-or-equal higherp@wer) % we must write it out in full: \ifthenelse{\NOT #2 < \value{higherp@wer}} {% Write down n: #2% } % Otherwise n has the same number of digits as m (i.e. both are % greater-or-equal power@fTen but less than higherp@wer) % and we have to check various criteria to decide whether we % leave out n's first digit: {% [2] % Compare the first digits of m and n. If the first digit % of n is greater than that of m, it (and the rest of n) must % be written down: \setcounter{firstdigit@fm}{#1/\value{power@fTen}}% \setcounter{firstdigit@fn}{#2/\value{power@fTen}}% \ifthenelse{\value{firstdigit@fn} > \value{firstdigit@fm}} {% Write down n: #2% } % Else m and n have the same first digit, and whether % it must be written down depends on m's following digits: {% [3] % The following criterion depends on the style! % Chicago, my style and my German style have it; % Oxford, MLA and minimal do not. % If m's first digit is followed by just a row of zeroes, % n must again be written out in full: \setcounter{firstdigit@fmfollowedbyzeroes} {\value{firstdigit@fm} * \value{power@fTen}}% % (dividing m by power@fTen to obtain % firstdigit@fm has cut off the following digits; % then multiplying again with power@fTen % replaces them with a row of zeroes) \ifthenelse {#1 = \value{firstdigit@fmfollowedbyzeroes}} {% Write down n: #2% } % If, however, m is not 1*power@fTen, 2*power@fTen, % ... or 9*power@fTen, then nothing stands in the way % of leaving out n's first digit -- % except if that's n's ONLY digit, % The following criterion is style-dependent! % or if m (and thus also n) are "teens" like 13 % (or 10, or 11, or 12) and 17: {% [4] % If power@fTen = 1, % This is universal. % The following isn't: % Oxford and my style have it; % minimal doesn't; % and Chicago, MLA and my German style have more general rules. % If power@fTen = 10, then write down BOTH of n's digits IF -- % -- Chicago/my German style: firstdigit@fm is in 1, 2, ..., 9; % -- MLA: firstdigit@fm is in 0, 1, ..., 9 (i.e. always). % OR power@fTen = 10 and m's first digit is 1, % write out n: \ifthenelse {\value{power@fTen} = 1 \OR \( \value{power@fTen} = 10 \AND \value{firstdigit@fm} = 1 \) } {% Write down n: #2% } % Else we can indeed leave out n's first digit. % Now we have to ask analogous questions % for the next digit, and so on: {% [5] \setcounter{new@m}{#1 - \value{firstdigit@fmfollowedbyzeroes}}% \setcounter{new@n}{#2 - \value{firstdigit@fn} * \value{power@fTen}}% \setcounter{higherp@wer}{\value{power@fTen}}% \setcounter{power@fTen}{\value{power@fTen}/10}% \write@llorlosetheleadingdigit{\arabic{new@m}}{\arabic{new@n}}% }% [5] }% [4] }% [3] }% [2] }% End of \newcommand{\write@llorlosetheleadingdigit}