# Remove trailing zeros when using siunitx

Consider the following example:

\documentclass{article}

\usepackage{multido}
\usepackage[
round-mode = places,
round-precision = 4
]{siunitx}

\ExplSyntaxOn
\cs_new_eq:NN \calc \fp_eval:n
\ExplSyntaxOff

\newcommand*\horse[1]{\calc{3.5*sin(pi/#1)}}

\begin{document}

\end{document}


Is it possible to remove the trailing zeros from the numbers? (In this case it means getting 3.5 instead of 3.5000 and 1.75 instead of 1.7500.)

Update

It seems that it's not possible to achieve what I would like; should the question therefore be closed?

-
You've asked for 4 places of precision: that's what you've got –  Joseph Wright Jan 11 at 14:04
@JosephWright The problem is that I would like the numbers with no trailing zeros to have four decimals precision. –  Svend Tveskæg Jan 11 at 14:06
Those numbers do have four decimal place precision. The trailing zeroes in 3.5000 signal that the true value is between 3.49995 and 3.50005. Think carefully about why you want to remove them. –  Ethan Bolker Jan 11 at 14:24
Remember: siunitx is a package for dealing with physical measurements and quantities. You can't have 7/2 cm or whatever: you can have 3.5000 cm with an uncertainly in as @EthanBolker suggests. Also, if you really want to print a fraction within say \SI then parse-numbers = false is available. –  Joseph Wright Jan 12 at 9:41
@SvendTveskæg I will see what I can come up with in the next release, of course! –  Joseph Wright Jan 12 at 9:46

You can use xintfrac. The package should have a native variant to its \xintTrunc or \xintRound routines which would strip trailing zeros, for lack of it I wrote a quick hack.

This initial hack was not completely satisfying (bad handling of integers). Here are two methods.

Update: the second method now allows two optional parameters, the first one is the number of digits after decimal mark (default 4), the second one is the decimal mark (default .). And this is expandable.

\documentclass{article}
\usepackage{expl3}

\usepackage{multido}
% \usepackage[
%   round-mode = places,
%   round-precision = 4
% ]{siunitx}

\ExplSyntaxOn
\cs_new_eq:NN \calc \fp_eval:n
\ExplSyntaxOff

\newcommand*\horse[1]{\calc{3.5*sin(pi/#1)}}
\newcommand*\horsenegative[1]{\calc{-3.5*sin(pi/#1)}}

\usepackage{xintfrac}

%///////////////////////////////////////////////////////////////////////
\makeatletter
% quickly written, there might be a simpler way
% you can modify \myNum@ to replace the dot by a comma if you prefer
% this method will work up to nine fixed point digits after decimal mark
% works also with negative numbers

% \def\myNum@ #1.{\the\numexpr #1.}% <- replace the last dot by the sep
%                                 % you need
% \newcommand*{\myNum}[1]{\xintRev{\expandafter\expandafter\expandafter
%                                  \myNum@\xintRev{\xintRound{4}{#1}}}}
%
%\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

% but this had problems: would not handle well the case of integers, and even
% crash on zero, (\xintRound then does not print 0.0000 but just 0 without a
% dot). Here are now two general methods:

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% method allowing customizing on output of the decimal mark:
% (but needs some modifications to switch from 4 to another number of digits)
\newcommand*{\myNum}[1]{\expandafter\myNum@
\romannumeral0\xintround {4}{#1}0000\relax }
\def\myNum@ #1{\if#10\expandafter\myNum@zero\fi \myNum@@ #1}
\def\myNum@@ #1.#20000#3\relax{\ifx\relax#2\relax \expandafter\myNum@int\fi
#1,#2}% <- we use a comma as decimal mark
% as comma was used above, must also be used here:
\def\myNum@int #1,{#1}% <- case of an integral number (positive or negative)
\def\myNum@zero #1\relax{0}% <- case of zero

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% another way, easily generalized to any given number of digits,
%  (actually, generalization already done: nb of digits is optional arg)
% \newcommand*{\myNumVar}[2][4]{\expandafter\expandafter\expandafter
%                            \myNumVar@\xintREZ{\xintRound {#1}{#2}}}
% \def\myNumVar@ #1/1[#2]%
% {\xintifSgn {#2}{\xintTrunc {-#2}{#1[#2]}}{#1}{\xintNum{#1[#2]}}}

% now allows arbitrary separator as second optional argument:

% **** and is expandable! ****

\catcode_ 11
\def\myNumVar #1{\myNumVar_chkopta #1\Z }
\def\myNumVar_chkopta #1{\ifx [#1\expandafter\myNumVar_opta
\else\expandafter\myNumVar_noopta
\fi #1}
\def\myNumVar_noopta #1\Z {\expandafter\expandafter\expandafter
\myNumVar@\xintREZ{\xintRound {4}{#1}}.}
\def\myNumVar_opta [\Z #1]#2{\myNumVar_chkoptb #2\Z {#1}}
\def\myNumVar_chkoptb #1{\ifx [#1\expandafter\myNumVar_optb
\else\expandafter\myNumVar_nooptb
\fi #1}
\def\myNumVar_optb [\Z #1#2]#3{\expandafter\expandafter\expandafter
\myNumVar@\xintREZ{\xintRound {#1}{#3}}{#2}}
\def\myNumVar_nooptb #1\Z #2{\expandafter\expandafter\expandafter
\myNumVar@\xintREZ{\xintRound {#2}{#1}}.}
\catcode_ 8

\def\myNumVar@ #1/1[#2]#3%
{\xintifSgn {#2}{\expandafter\expandafter\expandafter
\myNumVar@@ \xintTrunc {-#2}{#1[#2]}.{#3}}%
{#1}%
{\xintNum{#1[#2]}}}

\def\myNumVar@@ #1.#2.#3{#1#3#2}

\makeatother

\begin{document}

\verb|\myNum| uses a comma on output:

\verb|\myNumVar| has an optional argument to specify the number of digits
(possibly zero) after the dot as decimal mark:

\verb|\myNumVar| has a \textbf{second} optional argument to specify the
separator:

If you want to use crazy things like [ itself as separator you can do it:

\verb|\myNumVar [12][[]{stuff}|

But with ], use braces

\verb|\myNumVar [12][{]}]{stuff}|

Integral numbers do not have a decimal mark:

\myNum {-3.0000}=\myNumVar [5]{-3.0000}

\myNum {0.0000}=\myNumVar [13][!]{0.0000}

\myNum {-300.0000}=\myNumVar [7][;]{-300.0000}

\verb|\myNumVar| is expandable:\edef\test {\myNumVar [17][;]{1/1250}}

\verb|\edef\test {\myNumVar [17][;]{1/1250}}\meaning\test|
\texttt{\meaning\test}

\end{document}


-
I say this works with negative numbers, but there would be a problem with -3.0000, I don't have time to fix this now. Will provide complete solution later. (also I need to know if in case of 3.0000 the wanted thing is 3 or 3.). –  jfbu Feb 11 at 12:08
3.0000 --> 3. Thank you for the solution (and your upcomming improvement)! –  Svend Tveskæg Feb 11 at 12:18
@SvendTveskæg glad if it helps. I have replaced the initial slightly deficient hack by two methods. In the second method too, it would not be that hard now to add one extra layer to replace the dot by anything you want as decimal mark (on output). –  jfbu Feb 11 at 14:29
Really nice. If you would generalize it to be abel to take both . and , as decimal separator, it would be really cool. :) –  Svend Tveskæg Feb 11 at 14:33
@SvendTveskæg I have extended the second method to allow to specify the separator as a second optional argument. Notice that both the first and now the second method are completely expandable macros. –  jfbu Feb 11 at 16:07

A recommended solution with fp package.

\documentclass[preview,border=12pt,12pt]{standalone}
\usepackage[nomessages]{fp}
\usepackage{multido}
\newcommand*\horse[1]{\FPeval\calc{clip(trunc(3.5*sin(pi/#1):6))}\calc}

\begin{document}

@SvendTveskæg: Yes, just pass it to \num with your siunitx settings. Expansion should be carefully considered, ask other people in the chat room to fix the expansion problem if you want to pass the value to \num. –  cyanide-based food Jan 12 at 10:19