\IfDecimal 返回一个错误数字,该数字过大且小数点很大。我的目标是如果数字为数字,则打印四舍五入到位数的百分比,否则只打印参数的值。有没有办法绕过这个大小限制,或者有没有其他方法可以解决这个问题,因为我还不知道我是否有可解析的数字?\SomePerc 是一个简化的宏,我正在尝试使用。SomePerc 的输入要么是浮点数,要么是“-”(作为破折号而不是负数)
\documentclass[]{article}
\usepackage{siunitx}
\usepackage{xstring}
\newcommand\SomePerc[1]{
\IfDecimal{#1}
{\qty[ exponent-mode = fixed,
fixed-exponent = 0,
drop-exponent=true,
drop-zero-decimal=true,
round-mode=places,
round-precision =2]{#1e2}{\percent}
}
{#1}
}
\begin{document}
\IfDecimal{0.05479140921}{true}{false}
\IfDecimal{0.0547914092}{true}{false}
\num{0.054791409210}
\SomePerc{0.05479140921}
\SomePerc{0.0547914092}
\end{document}
latex 编译器说:
Number too big. \IfDecimal{0.05479140921}
Number too big. \SomePerc{0.05479140921}
答案1
以下定义了\ifdecimal
一个可扩展、快速的测试,适用于任意大的数字和位置。它既适用于,
和.
作为小数分隔符,也适用于任意多个符号。所有至少有一位数字、最多一位小数分隔符且没有空格的数都被视为十进制数。输入被完全扩展然后字符串化,其结果必须符合上述规则。
\documentclass{article}
\makeatletter
% needed to get a space inside of a definition
\newcommand\exparg@o[2]{\expanded{\unexpanded{#1}\expandafter}\expandafter{#2}}
% the front facing macro
\newcommand\ifdecimal[1]
{%
\expandafter\ifdecimal@space\detokenize\expanded{{#1}}\STOP
\ifdecimal@true
}
% true and false branching
\let\ifdecimal@true\@firstoftwo
\long\def\ifdecimal@false#1\ifdecimal@true#2#3{#3}
% check has no spaces
\exparg@o{\def\ifdecimal@space#1\STOP}%
{%
\@firstofone{\ifdecimal@space@#1\STOP\ifdecimal@false} \STOP % <- space
\ifdecimal@sign#1\MARK,\MARK
}
\def\ifdecimal@space@#1 #2\STOP{}
% strip leading signs
\def\ifdecimal@sign#1%
{%
\ifdecimal@sign@#1-\ifdecimal@sign@true+#1\ifdecimal@sign@true
+-\ifdecimal@dot#1%
}
\def\ifdecimal@sign@#1+-{}
\def\ifdecimal@sign@true#1+-\ifdecimal@dot#2{\ifdecimal@sign}
% turn one , into a . and then remove one decimal marker
\def\ifdecimal@dot#1,{\ifdecimal@dot@#1.}
\def\ifdecimal@dot@#1.{\ifdecimal@healmark\ifdecimal@empty#1}
\def\ifdecimal@healmark#1\MARK#2\MARK{#1\STOP}
% check is non-empty
\def\ifdecimal@empty#1\STOP
{%
\ifdecimal@empty@\MARK#1\STOP\ifdecimal@false\MARK\STOP
% the {0 \ifdecimal@done} works as the right delimiter to the input argument
\ifdecimal@digits#1{0 \ifdecimal@done}%
}
\def\ifdecimal@empty@#1\MARK\STOP{}
% check only digits left
\def\ifdecimal@digits#1%
{%
\ifnum9<1#1
\else
\expandafter\ifdecimal@false
\fi
\ifdecimal@digits
}
\def\ifdecimal@done#1\ifdecimal@digits{\fi}
\let\MARK\relax
\let\STOP\relax
\makeatother
% simple tests whether the macro works
\newcommand\ASSERT[2]
{%
\begingroup
\edef\tmpa{#2}%
\def\tmpb{#1}%
\expandafter
\endgroup
\ifx\tmpa\tmpb
\else
\GenericError{}{Assertion failed for \detokenize{#2}}{}{}%
\fi
}
\ASSERT{true}{\ifdecimal{0.}{true}{false}}
\ASSERT{true}{\ifdecimal{.0}{true}{false}}
\ASSERT{true}{\ifdecimal{0.0}{true}{false}}
\ASSERT{true}{\ifdecimal{00}{true}{false}}
\ASSERT{true}{\ifdecimal{+-+-+-+-00}{true}{false}}
\ASSERT{false}{\ifdecimal{.}{true}{false}}
\ASSERT{false}{\ifdecimal{+}{true}{false}}
\ASSERT{false}{\ifdecimal{-}{true}{false}}
\ASSERT{false}{\ifdecimal{+-}{true}{false}}
\ASSERT{false}{\ifdecimal{+-.}{true}{false}}
\ASSERT{false}{\ifdecimal{0+}{true}{false}}
\ASSERT{false}{\ifdecimal{0.0.0}{true}{false}}
\ASSERT{false}{\ifdecimal{a}{true}{false}}
\newcommand\five{5}
\ASSERT{true}{\ifdecimal{\five}{true}{false}}
\ASSERT{true}{\ifdecimal{\five .\five}{true}{false}}
\ASSERT{true}{\ifdecimal{\empty .\five}{true}{false}}
\ASSERT{false}{\ifdecimal{\five .\relax}{true}{false}}
\stop