17

Does anybody know how I could have LaTeX round a number like 2,386 so that I finally get only written 2,300?

I tried with siunitx and its option [round-mode=places,round-precision=-2] but it didn't work.

lockstep
  • 250,273
Frednight
  • 747
  • 2
    If you wanted to round to 2400 this would be easy: round figures rather than places. However, you seem to want to round down: is that correct? – Joseph Wright Aug 25 '14 at 15:58
  • 3
    Can you tell whether the comma is the decimal or a thousands separator? – egreg Aug 25 '14 at 16:20
  • 1
    @egreg I think the precision in the question implies the , is a thousand separator, but that doesn't help with the rounding down! – Joseph Wright Aug 25 '14 at 16:25

6 Answers6

14

Use siunitx and expl3.

\documentclass{article}
\usepackage{xparse,siunitx}

\ExplSyntaxOn
\NewDocumentCommand{\hundreds}{O{}m}
 {
  \num[#1]{\fp_eval:n { trunc(#2,-2) }}
 }
\ExplSyntaxOff

\begin{document}

\hundreds{2348}

\hundreds[group-four-digits,group-separator={,}]{2348}

\sisetup{group-four-digits,group-separator={,}}

\hundreds{2348}

\end{document}

enter image description here

egreg
  • 1,121,712
  • I was thinking about trunc but hadn't tried negative positions :-) Did you consider simply using a version of \fp_eval:n in the arg of \num but avoiding an entirely separate command? – Joseph Wright Aug 25 '14 at 16:38
  • @JosephWright The main problem is how to normalize the input: if one uses \hundreds{2,348}, the result will be wrong. But, IIRC, all such functions in siunitx are private. – egreg Aug 25 '14 at 16:40
10

Here's a LuaLaTeX-based solution to the problem of truncating a number to the closest multiple of 100. Positive and negative numbers are both truncated toward zero.

The \ensuremath macro, provided by the amsmath package, is used to make it unnecessary to keep track of whether the \mytrunc macro is used inside or outside of one of TeX's math mode environments.

enter image description here

% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{amsmath}  % for "\ensuremath" macro
% Create a TeX macro that invokes the lua library function 'math.fmod'
\newcommand\mytrunc[1]{%
   \ensuremath{ \directlua{ tex.sprint( #1 - math.fmod(#1,100) ) }}}

\begin{document}
2386 $\to$ \mytrunc{2386}

$-149$ $\to$ \mytrunc{-149}

$-186$ $\to$ \mytrunc{-186}
\end{document}
Mico
  • 506,678
5

Divide it by 100 then multiply the result by 100.

\documentclass{article}
\newcount\mycount
\mycount = 2386
\divide\mycount by 100
\multiply\mycount by 100
\begin{document}
\number\mycount
\end{document}
Ian Thompson
  • 43,767
  • 2
    This solution requires the number to be integer-valued, right? You may want to mention this fact explicitly, for the benefit of those readers who don't know much about TeX's count registers... – Mico Aug 25 '14 at 19:17
5

Just for fun with fp.

Rounding

\documentclass[preview,border=12pt,12pt,varwidth]{standalone}
\usepackage[nomessages]{fp}


\usepackage{pgffor}

\newcommand\rounder[2]{\FPeval\x{round(round(#1*pow(-#2,10):0)*pow(#2,10):0)}\x}

\begin{document}

\begin{itemize}
\foreach \i in {2440,2441,..., 2460}{\item \i\ is rounded to \rounder{\i}{2}.}
\end{itemize}

\end{document}

enter image description here

Truncating

\documentclass[preview,border=12pt,12pt,varwidth]{standalone}
\usepackage[nomessages]{fp}


\usepackage{pgffor}

\newcommand\rounder[2]{\FPeval\x{round(trunc(#1*pow(-#2,10):0)*pow(#2,10):0)}\x}

\begin{document}

\begin{itemize}
\foreach \i in {2440,2441,..., 2450}{\item \i\ is truncated to \rounder{\i}{2}.}
\end{itemize}

\end{document}

enter image description here

Bonus

Can you spot an oddity?

  • I don't why there are extra white spaces between to and the number. Confusing... – kiss my armpit Aug 25 '14 at 16:41
  • Use an \unskip to get rid of it and afterwards force a regular space. – Werner Aug 25 '14 at 16:43
  • 1
    Probably the usual unprotected end-of-line in fp. Oh, and it's odd that 2450 is rounded to 2400 instead of 2500. – egreg Aug 25 '14 at 16:43
  • 1
    @egreg I wouldn't say that it's odd at all that 2450 is rounded to 2400. Even based rounding is a very popular rounding technique for addressing the conundrum that is the halfway point between two numbers (0.5). I mainly know this technique as banker's rounding but it goes by a lot of names. 2050 --> 2000. 2150 --> 2200. 2250 --> 2200. 2350 --> 2400. Even based rounding tends to produce simpler math later than the parallel odd based rounding. – Mark Balhoff Aug 25 '14 at 18:09
  • @MarkBalhoff - But does this code produce "banker's rouding"? – Mico Aug 25 '14 at 18:32
  • @Mico I'm thinking yes since I just found the following comment near the top of the l3fp-round.dtx file in the LaTeX repository (link): "The \enquote{round to nearest} mode is the default. If the \meta{digit_2} is larger than~$5$, then round up. If it is less than~$5$, round down. If it is exactly $5$, then round such that \meta{digit_1} plus the result is even. In other words, round up if \meta{digit_1} is odd." – Mark Balhoff Aug 25 '14 at 19:44
  • @MarkBalhoff - Hmmm, when I run "cyanide-based food"'s code, I get \rounder{2150}{2} = 2100 instead of 2200. Similarly, \rounder{2350} = 2300 instead of 2400. Am I missing something about the essence of "banker's rounding"? Or does l3fp's actual rounding algorithm maybe not cohere with its stated method? – Mico Aug 25 '14 at 19:51
  • @cyanide-basedfood The unprotected end-of-line is at line 444 of fp-exp.sty. The one we already knew about (What makes my line get shifted to the left when I invoke \LoadConstants?) – egreg Aug 25 '14 at 20:16
  • @Mico Hmmm that is interesting. Do you get \rounder(2450) = 2400 as cyanide did above?? My curiosity will force me to dig deeper into the methodology when I have time. Maybe I can find time tonight. What you are showing makes it seem like a round toward zero for midpoint round which introduces an identical magnitude of rounding error to the presumption that 0.5 should round up. Not any worse. – Mark Balhoff Aug 25 '14 at 20:16
  • @MarkBalhoff - Indeed, the result of \rounder{2450}{2} is 2400, as is also shown in the original answer. – Mico Aug 25 '14 at 20:24
  • @Mico Seems perhaps that it doesn't line up with that code comment. All of your examples seem to match a round to zero approach to ties. This rounding is probably less common than round away from zero but does get used and has the same magnitude of bias as the latter. Based on my reading of the comments, round away from zero is what egreg and cyanide expected. – Mark Balhoff Aug 25 '14 at 20:31
  • For the record, contrary to the comments above, this has nothing to do with l3fp. fp is a different (older) package. – Bruno Le Floch Aug 06 '17 at 13:39
  • Thanks. Solution helped where I had conflicts with siunitx. Works fine with numprint pacage to get currencies rounded: \newcommand\rounder[2][2]{\FPeval\x{round(round(#2*pow(-#1,10):0)*pow(#1,10):0)}\numprint{\x}} – kregkob Mar 16 '19 at 10:11
3
\documentclass{article}
\makeatletter
\def\twodec#1{\expandafter\twodecB#1,,,\@nil}
\def\twodecB#1,#2#3#4\@nil{\ifx,#2 #1,000\else#1,#200\fi}
\makeatother
\begin{document}
\twodec{2}\par
\twodec{2,3}\par
\twodec{2,38}\par
\twodec{2,386}
\end{document}

enter image description here

2

For R users, an easy option is a file.Rnw file like that:

<<echo=F>>=
a <- 100
rounddown <- function(x){format(floor(x/a)*a,   big.mark = ",")} 
@

\documentclass{article}
\begin{document}
 Rounded down 2,326 is \Sexpr{rounddown(2326)}.
\end{document}

That with R CMD Sweave file.Rnw is converted to a true file.tex like that:

\documentclass{article}
\usepackage{Sweave}
\begin{document}
Rounded down 2,326 is 2,300.
\end{document}
Fran
  • 80,769