使用 siunitx 时删除尾随零

使用 siunitx 时删除尾随零

请考虑以下示例:

\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}

\multido{\i=2+1}{5}{\num{\horse{\i}}\quad}

\end{document}

输出

是否可以从数字中删除尾随的零?(在这种情况下,它意味着得到3.5而不是3.5000和 而1.75不是1.7500。)

更新

看来我无法实现我的愿望;因此这个问题应该结束吗?

答案1

您可以使用信特压裂。该包应该有一个本机变体\xintTrunc\xintRound例程,可以删除尾随零,由于缺少它,我编写了一个快速破解程序。

最初的这个 hack 并不完全令人满意(整数处理不好)。下面有两种方法。

更新:第二种方法现在允许可选参数,第一个是小数点后的位数(默认4),第二个是小数点(默认.)。这是可扩展

\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:

\multido{\i=2+1}{5}{\myNum{\horse{\i}}\quad}

\multido{\i=2+1}{5}{\myNum{\horsenegative{\i}}\quad}

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

\multido{\i=2+1}{5}{\myNumVar [12]{\horse{\i}}\quad}

\multido{\i=2+1}{5}{\myNumVar [12]{\horsenegative{\i}}\quad}

\multido{\i=2+1}{5}{\myNumVar [0]{\horse{\i}}\quad}

\multido{\i=2+1}{5}{\myNumVar [0]{\horsenegative{\i}}\quad}

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

\multido{\i=2+1}{5}{\myNumVar [12][,]{\horse{\i}}\quad}

\multido{\i=2+1}{5}{\myNumVar [12][,]{\horsenegative{\i}}\quad}

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

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

\multido{\i=2+1}{5}{\myNumVar [12][[]{\horse{\i}}\quad}

But with ], use braces

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

\multido{\i=2+1}{5}{\myNumVar [12][{]}]{\horse{\i}}\quad}


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}

删除零

答案2

自从3.0版从 2021 年开始,有一个选项round-pad似乎可以满足您的要求:

\documentclass{article}

\usepackage{multido}
\usepackage[
  round-mode = places,
  round-precision = 4,
  round-pad = false %% true by default
]{siunitx}

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

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

\begin{document}

\multido{\i=2+1}{5}{\num{\horse{\i}}\quad}

\end{document}

输出:

在此处输入图片描述

答案3

推荐使用包的解决方案fp

\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}
\multido{\i=2+1}{5}{\horse{\i}\quad}
\end{document}

在此处输入图片描述

答案4

你问,

是否可以删除数字后面的零?

使用 LuaLaTeX 非常简单 —— 不需要siunitx包及其\num宏。:-)

在此处输入图片描述

\documentclass{article}

\usepackage{luacode} % for '\luaexec' macro 
% Create 2 Lua functions, 'horse' and 'mynum':
\luaexec{
  function horse ( i )
    return ( 3.5 * math.sin ( math.pi / i ) )
  end
  function mynum ( j  )
    return ( string.format ( '\%.5g' , j ) )
  end
}
% Create a LaTeX wrapper macro for 'mynum' function:
\newcommand\mynum[1]{\directlua{tex.sprint(mynum(#1))}}

\begin{document}
\mynum{1.750000001}

\directlua { for i=2,6 do 
               tex.sprint ( mynum ( horse ( i ) ) .. '\\quad' )
             end
           }
\end{document}

相关内容