¿Cómo eliminar cero decimal en números?
Quiero escribir una macro para eliminar el cero en el decimal. por ejemplo, convertir 2.0a un 2número.
este es mi intento de eliminar un cero, pero no funciona y produce un error:
\documentclass[borders=2cm]{standalone}
\usepackage{tikz}
\newcommand{\isinteger}[1]{\pgfmathtruncatemacro{\intvar}{#1}
\def\newx{\pgfmathparse{10*(\intvar-#1)}\pgfmathresult}
\ifnum\newx=0
\intvar
\else
#1
\fi}
\begin{document}
\isinteger{1.5}
\end{document}
Errores:
Missing number, treated as zero. \isinteger{1.5}
Missing = inserted for \ifnum. \isinteger{1.5}
Missing number, treated as zero. \isinteger{1.5}
¿Alguna idea?
Respuestas
\documentclass{article}
\ExplSyntaxOn
\newcommand\isintegerTF[1]{
\fp_compare:nNnTF
{#1}={floor(#1)}
}
\ExplSyntaxOff
\begin{document}
\isintegerTF{2}{2 yes}{2 no}
\isintegerTF{1.5}{1.5 yes}{1.5 no}
\end{document}
Si solo desea imprimir un número entero como un número entero y un no entero como un número no entero, y dado que ya está usando pgfmath , le recomiendo usar \pgfmathprintnumber. Se describe en detalle en el capítulo 98 del manual de TikZ , pero lo siguiente parece hacer lo que desea:
\documentclass{article}
\usepackage{tikz}
\newcommand{\isinteger}[1]{\pgfmathprintnumber[int detect,fixed]{#1}}
\begin{document}
\isinteger{1.5}
\isinteger{1.0}
\end{document}
Esto imprime 1.5y 1, respectivamente.
Otra opción es utilizar \numdesde siunitx :
\documentclass{article}
\usepackage{siunitx}
\newcommand{\isinteger}[1]{\num[zero-decimal-to-integer=true]{#1}}
\begin{document}
\isinteger{1.5}
\isinteger{1.0}
\end{document}
Una variante de la respuesta de David, si el objetivo es simplemente no imprimir ceros al final:
\documentclass{article}
\usepackage{xfp}
\begin{document}
\fpeval{1}
\fpeval{1.0}
\fpeval{1.5}
\fpeval{14/5-4/5}
\fpeval{round(4*pi*3.4^3/3,0)} % round to integer
\end{document}
Tenga en cuenta que el fpmódulo de expl3(que se usa aquí) es mucho más preciso que las utilidades de punto flotante PGF.
Solo por el bien de la variedad, aquí hay una implementación basada en LuaLaTeX de \IsInteger.
El argumento de \IsIntegerpuede ser un número o una expresión que se evalúa como un número de acuerdo con las reglas léxicas de Lua. Si, por otro lado, intenta ejecutar \Integer{"u"}, obtendrá un mensaje de error como este:
mal argumento # 1 para 'piso' (número esperado, cadena obtenida)
% !TEX TS-program = lualatex
\documentclass{article}
\directlua{%
function IsInteger ( x )
y = math.floor ( x )
tex.sprint ( x==y and y or x )
end}
\newcommand\IsInteger[1]{\directlua{IsInteger(#1)}}
\begin{document}
\IsInteger{1.5}, \IsInteger{1.0}, \IsInteger{math.pi}, \IsInteger{math.exp(math.log(1))}
\end{document}
Puedo ofrecer una rutina ampliable \normalizenumberpara "normalizar" números.
Para explicar cómo \normalizenumberfunciona, permítanme definir, además de lo que se define de la gramática de TeX en el TeXBook en la notación Backus / Naur, una cantidad ⟨separador decimal⟩ :
⟨Separador decimal⟩ → . 12 | , 12
Sintaxis de \normalizenumberis:
\normalizenumber⟨undelimited argument⟩
Caso 1:
Los tokens que se forman ⟨undelimited argument⟩cumplen con el patrón
⟨Signos opcionales⟩ ⟨constante entera⟩ ⟨un espacio opcional⟩
En el caso 1
- Los "signos opcionales" se convierten como se describe a continuación y se entregan.
- Se entrega una "constante entera" con todos los ceros iniciales eliminados.
En caso de que la eliminación de todos los ceros iniciales produzca un vacío, se entrega un solo dígito .012 - Se elimina ⟨un espacio opcional⟩ .
Caso 2:
Los tokens que se forman ⟨undelimited argument⟩cumplen con el patrón
⟨Signos opcionales⟨ ⟨constante entera⟩ ⟨separador decimal⟩ ⟨constante entera⟩ ⟨un espacio opcional⟩
En el caso 2
- Los "signos opcionales" se convierten como se describe a continuación y se entregan.
- La primera / izquierda⟩ constante entera⟩ se entrega con todos los ceros iniciales eliminados.
En caso de que la eliminación de todos los ceros iniciales produzca un vacío, se entrega un solo dígito .012 - Si la eliminación de todos los ceros finales de la segunda / derecha ⟨constante entera⟩ no produce vacío, entonces se entrega el ⟨separador decimal⟨ .
- La ⟨constante entera second segunda / derecha se entrega con todos los ceros finales eliminados.
- Se elimina ⟨un espacio opcional⟩ .
En todos los demás casos, los tokens que forman el ⟨undelimited argument⟩se entregan sin cambios. Se eliminan los
tirantes rizados que delimitan el ⟨undelimited argument⟩.
En cualquier caso, debido a la \romannumeral0expansión, el resultado se entrega después de dos pasos de expansión / "golpeando" \normalizenumbercon \expandafterdos veces.
Las cosas que se acaban de decir implican que, por ejemplo, \normalizenumber{1.}retorna 1.sin cambios porque el ⟨argumento 1. no delimitado⟩ no es del patrón descrito para el caso 1 ni es del patrón descrito para el caso 2. \normalizenumber{1.000}produce 1—el ⟨argumento no delimitado⟩ 1.000 es del patrón descrito para el caso 2.
Conversión de ⟨signos opcionales⟩
En caso de que los " signos opcionales" denoten un número no negativo, no se les devuelve ningún token.
En caso de que los " signos opcionales" denoten un número negativo, se les devuelve un único símbolo de carácter explícito . Si el valor absoluto del número a normalizar es 0, no obtendrá un signo; no obtendrá, pero obtendrá .-12-00
La expansión de \normalizenumber's ⟨undelimited argument⟩
\normalizenumberen un bucle recursivo de cola examina su argumento en forma de token: Si el primer token del ⟨argumento no delimitado⟩ no implica que el ⟨argumento no delimitado⟩ no cumple con el patrón del caso 1 ni cumple con el patrón del caso 2, entonces será eliminado del ⟨argumento no delimitado⟩ para la siguiente iteración y en la siguiente iteración \normalizenumber"buscará" el primer token del ⟨argumento no delimitado⟩ restante .
Hay un \ifinterruptor \ifnormalizenumberexpandarg.
Si dice \normalizenumberexpandargfalse, entonces \normalizenumberno expande los tokens expandibles durante el examen y encontrar un token expandible implica que el ⟨argumento no delimitado⟩ no cumple con el patrón descrito para el caso 1 ni cumple con el patrón descrito para el caso 2.
Si dice \normalizenumberexpandargtrue, entonces en cada iteración encontrar que el primer token del ⟩argumento no delimitado⟩ es expandible dispara "golpearlo" con \expandaftery en la siguiente iteración examinando el resultado. Expandir el primer token del ⟨argumento no delimitado⟩ puede afectar los siguientes tokens del ⟨argumento no delimitado⟩ .
Úselo \normalizenumberexpandargtruecon cuidado y con cierta sospecha:
si el primer token está desequilibrado \elseo \fidesequilibrado \csname, puede recibir todo tipo de mensajes de error extraños. Si el primer token se define para activar cosas que afectan a los tokens más allá de la llave de cierre del ⟨argumento no delimitado⟩ , entonces el flujo del programa puede volverse impredecible. Si el primer token está definido para entregarse solo, puede terminar en un bucle sin fin.
\errorcontextlines=10000
\documentclass{article}
\makeatletter
%%=============================================================================
%% Paraphernalia:
%% \UD@firstoftwo, \UD@secondoftwo, \UD@Exchange, \UD@Removespace
%% \UD@CheckWhetherNull, \UD@CheckWhetherLeadingSpace, \UD@ExtractFirstArg
%%=============================================================================
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@Exchange[2]{#2#1}%
\@ifdefinable\UD@Removespace{\UD@Exchange{ }{\def\UD@Removespace}{}}%
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
\romannumeral0\expandafter\UD@secondoftwo\string{\expandafter
\UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
\UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
\UD@secondoftwo\string}\expandafter\expandafter\UD@firstoftwo{ }{}%
\UD@secondoftwo}{\expandafter\expandafter\UD@firstoftwo{ }{}\UD@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument's first token is a catcode-1-character
%%.............................................................................
%% \UD@CheckWhetherBrace{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked has leading
%% catcode-1-token>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked has no leading
%% catcode-1-token>}%
\newcommand\UD@CheckWhetherBrace[1]{%
\romannumeral0\expandafter\UD@secondoftwo\expandafter{\expandafter{%
\string#1.}\expandafter\UD@firstoftwo\expandafter{\expandafter
\UD@secondoftwo\string}\expandafter\expandafter\UD@firstoftwo{ }{}%
\UD@firstoftwo}{\expandafter\expandafter\UD@firstoftwo{ }{}\UD@secondoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether brace-balanced argument starts with a space-token
%%.............................................................................
%% \UD@CheckWhetherLeadingSpace{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is a
%% space-token>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is not
%% a space-token>}%
\newcommand\UD@CheckWhetherLeadingSpace[1]{%
\romannumeral0\UD@CheckWhetherNull{#1}%
{\expandafter\expandafter\UD@firstoftwo{ }{}\UD@secondoftwo}%
{\expandafter\UD@secondoftwo\string{\UD@CheckWhetherLeadingSpaceB.#1 }{}}%
}%
\newcommand\UD@CheckWhetherLeadingSpaceB{}%
\long\def\UD@CheckWhetherLeadingSpaceB#1 {%
\expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo{}#1}%
{\UD@Exchange{\UD@firstoftwo}}{\UD@Exchange{\UD@secondoftwo}}%
{\UD@Exchange{ }{\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter}\expandafter\expandafter
\expandafter}\expandafter\UD@secondoftwo\expandafter{\string}%
}%
%%=============================================================================
%% Extract K-th inner undelimited argument:
%%
%% \UD@ExtractKthArg{<integer K>}{<list of undelimited args>}
%%
%% In case there is no K-th argument in <list of indelimited args> :
%% Does not deliver any token.
%% In case there is a K-th argument in <list of indelimited args> :
%% Does deliver that K-th argument with one level of braces removed.
%%
%% Examples:
%%
%% \UD@ExtractKthArg{0}{ABCDE} yields: <nothing>
%%
%% \UD@ExtractKthArg{3}{ABCDE} yields: C
%%
%% \UD@ExtractKthArg{3}{AB{CD}E} yields: CD
%%
%% \UD@ExtractKthArg{4}{{001}{002}{003}{004}{005}} yields: 004
%%
%% \UD@ExtractKthArg{6}{{001}{002}{003}} yields: <nothing>
%%
%%=============================================================================
\newcommand\UD@ExtractKthArg[1]{%
\romannumeral0%
% #1: <integer number K>
\expandafter\UD@ExtractKthArgCheck
\expandafter{\romannumeral\number\number#1 000}%
}%
\newcommand\UD@ExtractKthArgCheck[2]{%
\UD@CheckWhetherNull{#1}{ }{%
\expandafter\UD@ExtractKthArgLoop\expandafter{\UD@firstoftwo{}#1}{#2}%
}%
}%
\newcommand\UD@ExtractKthArgLoop[2]{%
\expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo#2{}.}{ }{%
\UD@CheckWhetherNull{#1}{%
\UD@ExtractFirstArgLoop{#2UD@SelDOm}%
}{%
\expandafter\UD@Exchange\expandafter{\expandafter{\UD@firstoftwo{}#2}}%
{\expandafter\UD@ExtractKthArgLoop\expandafter{\UD@firstoftwo{}#1}}%
}%
}%
}%
\@ifdefinable\UD@RemoveTillUD@SelDOm{%
\long\def\UD@RemoveTillUD@SelDOm#1#2UD@SelDOm{{#1}}%
}%
\newcommand\UD@ExtractFirstArgLoop[1]{%
\expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo{}#1}%
{\UD@firstoftwo{\expandafter}{} \UD@secondoftwo{}#1}%
{\expandafter\UD@ExtractFirstArgLoop\expandafter{\UD@RemoveTillUD@SelDOm#1}}%
}%
%%=============================================================================
%% Fork if argument, which must be a single token, is
%% 0/1/2/3/4/5/6/7/8/9/+/-/./,/<space token>/<expandable token>/<something else>
%% (total: 17 cases)
%%-----------------------------------------------------------------------------
\@ifdefinable\UD@GobbleToExclam{\long\def\UD@GobbleToExclam#1!{}}%
%%-----------------------------------------------------------------------------
\@ifdefinable\UD@normalizenumberfork{%
\long\def\UD@normalizenumberfork#1!0!1!2!3!4!5!6!7!8!9!+!-!,!.!#2#3!!!!{#2}%
}%
\newcommand\UD@normalizenumberloopfork[1]{%
\expandafter\UD@CheckWhetherNull\expandafter{\UD@GobbleToExclam#1!}{%
\UD@normalizenumberfork
!#1!1!2!3!4!5!6!7!8!9!+!-!,!.!{1}% <digit> 0_12
!0!#1!2!3!4!5!6!7!8!9!+!-!,!.!{2}% <digit> 1_12
!0!1!#1!3!4!5!6!7!8!9!+!-!,!.!{3}% <digit> 2_12
!0!1!2!#1!4!5!6!7!8!9!+!-!,!.!{4}% <digit> 3_12
!0!1!2!3!#1!5!6!7!8!9!+!-!,!.!{5}% <digit> 4_12
!0!1!2!3!4!#1!6!7!8!9!+!-!,!.!{6}% <digit> 5_12
!0!1!2!3!4!5!#1!7!8!9!+!-!,!.!{7}% <digit> 6_12
!0!1!2!3!4!5!6!#1!8!9!+!-!,!.!{8}% <digit> 7_12
!0!1!2!3!4!5!6!7!#1!9!+!-!,!.!{9}% <digit> 8_12
!0!1!2!3!4!5!6!7!8!#1!+!-!,!.!{10}% <digit> 9_12
!0!1!2!3!4!5!6!7!8!9!#1!-!,!.!{11}% <plus or minus> +_12
!0!1!2!3!4!5!6!7!8!9!+!#1!,!.!{12}% <plus or minus> -_12
!0!1!2!3!4!5!6!7!8!9!+!-!#1!.!{13}% <decimal constant> ,_12
!0!1!2!3!4!5!6!7!8!9!+!-!,!#1!{14}% <decimal constant> ._12
!0!1!2!3!4!5!6!7!8!9!+!-!,!.!{%
\ifcat\noexpand#1 \expandafter\UD@firstoftwo\else\expandafter\UD@secondoftwo\fi
{15}% <space token> differing from explicit character token of catcode 10
% and charcode 32; removable as undelimited argument
{%
\expandafter\ifx\noexpand#1#1%
\expandafter\UD@firstoftwo\else\expandafter\UD@secondoftwo\fi
{18}% something else which is not allowed
{17}% expandable token
}%
}%
!!!!%
}{18}% Case: #1 contains !_12 , therefore is something else which is not
% allowed
}%
%%=============================================================================
%% \normalizenumber{<argument>}
%%-----------------------------------------------------------------------------
\newcommand\normalizenumber[1]{%
\romannumeral0%
\normalizenumberloop{#1}{}{}{#1}{\UD@firstoftwo}{}{\UD@firstoftwo}{}%
}%
\newif\ifnormalizenumberexpandarg\normalizenumberexpandargfalse
\newcommand\normalizenumberloop[8]{%
% #1 - argument to iterate
% #2 - leading zero if found
% #3 - optional minus sign
% #4 - argument untouched
% #5 - decimal separator not/already found - \UD@firstoftwo/\UD@secondoftwo
% #6 - zero-decimals collected so far
% #7 - sign-check on/off - \UD@firstoftwo/\UD@secondoftwo
% #8 - significant digits collected so far
\UD@CheckWhetherNull{#1}{%
\UD@CheckWhetherNull{#8}{\UD@CheckWhetherNull{#2}{ #4}{ #2}}{ #3#8}%
}{%
\UD@ExtractKthArg{%
%-------------------------------------------------------------------------
% \UD@ExtractKthArg's <integer K>:
%-------------------------------------------------------------------------
% Code for calculating \UD@ExtractKthArg's <integer K>
\UD@CheckWhetherBrace{#1}{%
18% argument to iterate's 1st token has catcode 1, therefore is not
% allowed.
}{%
\UD@CheckWhetherLeadingSpace{#1}{%
16% explicit character token of catcode 10 and charcode 32; not
% removable as undelimited argument
}{%
\expandafter\UD@normalizenumberloopfork
\expandafter{\romannumeral0\UD@ExtractFirstArgLoop{#1UD@SelDOm}}%
}%
}%
}{%
%-------------------------------------------------------------------------
% \UD@ExtractKthArg's <list of undelimited args>:
%-------------------------------------------------------------------------
% \UD@ExtractKthArg's <list of undelimited args>'s 1st argument:
% \UD@ExtractKthArg's 1st argument yields the number 1, thus #1's
% 1st token is <digit> 0_12
{%
#5{%
\UD@CheckWhetherNull{#8}{%
\UD@firstoftwo{%
\expandafter\normalizenumberloop\expandafter{\UD@firstoftwo{}#1}{0}{#3}{#4}{#5}{}{\UD@secondoftwo}{#8}%
}%
}{\UD@Exchange{{#80}}}%
}{%
\UD@firstoftwo{%
\expandafter\normalizenumberloop
\expandafter{\UD@firstoftwo{}#1}{#2}%
{#3}{#4}{#5}{#60}{\UD@secondoftwo}{#8}%
}%
}%
}%
%-----------------------------------------------------------------------
% \UD@ExtractKthArg's <list of undelimited args>'s 2nd argument:
% \UD@ExtractKthArg's 1st argument yields the number 2, thus #1's
% 1st token is <digit> 1_12
{\UD@Exchange{{#8#61}}}%
%-----------------------------------------------------------------------
% \UD@ExtractKthArg's <list of undelimited args>'s 3rd argument:
% \UD@ExtractKthArg's 1st argument yields the number 3, thus #1's
% 1st token is <digit> 2_12
{\UD@Exchange{{#8#62}}}%
%-----------------------------------------------------------------------
% \UD@ExtractKthArg's <list of undelimited args>'s 4th argument:
% \UD@ExtractKthArg's 1st argument yields the number 4, thus #1's
% 1st token is <digit> 3_12
{\UD@Exchange{{#8#63}}}%
%-----------------------------------------------------------------------
% \UD@ExtractKthArg's <list of undelimited args>'s 5th argument:
% \UD@ExtractKthArg's 1st argument yields the number 5, thus #1's
% 1st token is <digit> 4_12
{\UD@Exchange{{#8#64}}}%
%-----------------------------------------------------------------------
% \UD@ExtractKthArg's <list of undelimited args>'s 6th argument:
% \UD@ExtractKthArg's 1st argument yields the number 6, thus #1's
% 1st token is <digit> 5_12
{\UD@Exchange{{#8#65}}}%
%-----------------------------------------------------------------------
% \UD@ExtractKthArg's <list of undelimited args>'s 7th argument:
% \UD@ExtractKthArg's 1st argument yields the number 7, thus #1's
% 1st token is <digit> 6_12
{\UD@Exchange{{#8#66}}}%
%-----------------------------------------------------------------------
% \UD@ExtractKthArg's <list of undelimited args>'s 8th argument:
% \UD@ExtractKthArg's 1st argument yields the number 8, thus #1's
% 1st token is <digit> 7_12
{\UD@Exchange{{#8#67}}}%
%-----------------------------------------------------------------------
% \UD@ExtractKthArg's <list of undelimited args>'s 9th argument:
% \UD@ExtractKthArg's 1st argument yields the number 9, thus #1's
% 1st token is <digit> 8_12
{\UD@Exchange{{#8#68}}}%
%-----------------------------------------------------------------------
% \UD@ExtractKthArg's <list of undelimited args>'s 10th argument:
% \UD@ExtractKthArg's 1st argument yields the number 10, thus #1's
% 1st token is <digit> 9_12
{\UD@Exchange{{#8#69}}}%
%-----------------------------------------------------------------------
% \UD@ExtractKthArg's <list of undelimited args>'s 11th argument:
% \UD@ExtractKthArg's 1st argument yields the number 11, thus #1's
% 1st token is <plus or minus> +_12
{%
\UD@firstoftwo{%
#7{%
\expandafter\UD@CheckWhetherNull
\expandafter{\UD@firstoftwo{}#1}{ #4}{%
\expandafter\normalizenumberloop
\expandafter{\UD@firstoftwo{}#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}%
}%
}{ #4}%
}%
}%
%-----------------------------------------------------------------------
% \UD@ExtractKthArg's <list of undelimited args>'s 12th argument:
% \UD@ExtractKthArg's 1st argument yields the number 12, thus #1's
% 1st token is <plus or minus> -_12
{%
\UD@firstoftwo{%
#7{%
\expandafter\UD@CheckWhetherNull
\expandafter{\UD@firstoftwo{}#1}{ #4}{%
\UD@CheckWhetherNull{#3}{\UD@Exchange{{-}}}{\UD@Exchange{{}}}%
{\expandafter\normalizenumberloop\expandafter{\UD@firstoftwo{}#1}{#2}}%
{#4}{#5}{#6}{#7}{#8}%
}%
}{ #4}%
}%
}%
%-----------------------------------------------------------------------
% \UD@ExtractKthArg's <list of undelimited args>'s 13th argument:
% \UD@ExtractKthArg's 1st argument yields the number 13, thus #1's
% 1st token is <decimal constant> ,_12
{%
\UD@firstoftwo{%
#5{%
\expandafter\UD@CheckWhetherNull
\expandafter{\UD@firstoftwo{}#1}{ #4}{%
\UD@CheckWhetherNull{#2#8}{ #4}{%
\UD@CheckWhetherNull{#8}{\UD@Exchange{{#2}}}{\UD@Exchange{{#8}}}%
{%
\expandafter\normalizenumberloop\expandafter{\UD@firstoftwo{}#1}%
{#2}{#3}{#4}{\UD@secondoftwo}{,}{\UD@secondoftwo}%
}%
}%
}%
}{ #4}%
}%
}%
%-----------------------------------------------------------------------
% \UD@ExtractKthArg's <list of undelimited args>'s 14th argument:
% \UD@ExtractKthArg's 1st argument yields the number 14, thus #1's
% 1st token is <decimal constant> ._12
{%
\UD@firstoftwo{%
#5{%
\expandafter\UD@CheckWhetherNull
\expandafter{\UD@firstoftwo{}#1}{ #4}{%
\UD@CheckWhetherNull{#2#8}{ #4}{%
\UD@CheckWhetherNull{#8}{\UD@Exchange{{#2}}}{\UD@Exchange{{#8}}}%
{%
\expandafter\normalizenumberloop\expandafter{\UD@firstoftwo{}#1}%
{#2}{#3}{#4}{\UD@secondoftwo}{.}{\UD@secondoftwo}%
}%
}%
}%
}{ #4}%
}%
}%
%-----------------------------------------------------------------------
% \UD@ExtractKthArg's <list of undelimited args>'s 15th argument:
% \UD@ExtractKthArg's 1st argument yields the number 15, thus #1's
% 1st token is a <space token> differing from explicit character
% token of catcode 10 and charcode 32 and is removable as
% undelimited argument
{%
\UD@firstoftwo{%
#7{\UD@firstoftwo}{%
\expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo{}#1}%
}%
{%
\expandafter\normalizenumberloop
\expandafter{\UD@firstoftwo{}#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}%
}%
{ #4}%
}%
}%
%-----------------------------------------------------------------------
% \UD@ExtractKthArg's <list of undelimited args>'s 16th argument:
% \UD@ExtractKthArg's 1st argument yields the number 16, thus #1's
% 1st token is a <space token>, more precisely an explicit
% character token of catcode 10 and charcode 32 and is not removable
% as undelimited argument
{%
\UD@firstoftwo{%
#7{\UD@firstoftwo}{%
\expandafter\UD@CheckWhetherNull\expandafter{\UD@Removespace#1}%
}%
{%
\expandafter\normalizenumberloop
\expandafter{\UD@Removespace#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}%
}%
{ #4}%
}%
}%
%-----------------------------------------------------------------------
% \UD@ExtractKthArg's <list of undelimited args>'s 17th argument:
% \UD@ExtractKthArg's 1st argument yields the number 17, thus #1's
% 1st token is expandable.
{%
\UD@firstoftwo{%
\ifnormalizenumberexpandarg
\expandafter\UD@firstoftwo\else\expandafter\UD@secondoftwo\fi
{\expandafter\normalizenumberloop\expandafter{#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}}%
{ #4}%
}%
}%
%-----------------------------------------------------------------------
% \UD@ExtractKthArg's <list of undelimited args>'s 18th argument:
% \UD@ExtractKthArg's 1st argument yields the number 18, thus #1's
% 1st token is not allowed with numbers that can be normalized.
{%
\UD@firstoftwo{ #4}%
}%
%-------------------------------------------------------------------------
% End of \UD@ExtractKthArg's <list of undelimited args>.
%-------------------------------------------------------------------------
}%
{\expandafter\normalizenumberloop\expandafter{\UD@firstoftwo{}#1}%
{#2}{#3}{#4}{#5}{}{\UD@secondoftwo}%
}%
}%
}%
%%.............................................................................
\makeatother
% Test \normalizenumber by applying it inside the definition-text of \test:
\newcommand\Test[1]{%
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\test
\expandafter\expandafter\expandafter{#1}%
\texttt{(\meaning\test)}%
}%
\makeatletter\let\sptoken= \@sptoken\makeatother
\begin{document}
\null\kern-2cm
The following either comply the pattern described in case 1 or comply the pattern described in case 2:
01: \Test{\normalizenumber{-\sptoken\sptoken-\sptoken++\sptoken00000.0000\sptoken}}
02: \Test{\normalizenumber{-\sptoken\sptoken-\sptoken++\sptoken - 8\sptoken}}
03: \Test{\normalizenumber{+-+00000}}
04: \Test{\normalizenumber{-++++0}}
05: \Test{\normalizenumber{---00000.000010000}}
06: \Test{\normalizenumber{--+-0003.9}}
07: \Test{\normalizenumber{+-+00087}}
08: \Test{\normalizenumber{+ -+00024}}
09: \Test{\normalizenumber{--87.0000}}
10: \Test{\normalizenumber{+--0015.00000010000700000}}
11: \Test{\normalizenumber{+98.0000 }}
12: \Test{\normalizenumber{4.50000}}
13: \Test{\normalizenumber{2.50000 }}
14: \Test{\normalizenumber{7,4}}
15: \Test{\normalizenumber{67}}
16: \Test{\normalizenumber{-15}}
17: \Test{\normalizenumber{-+ +-+ 15 }}
18: \Test{\normalizenumber{67,0000}}
19: \Test{\normalizenumber{67,0000001}}
20: \Test{\normalizenumber{68,0000 }}
21: \Test{\normalizenumber{2,80000}}
22: \Test{\normalizenumber{7,50000 }}
23: \Test{\normalizenumber{1,50000 }}
\kern\dp\strutbox
\hrule
\kern\dp\strutbox
The following don't comply any of these two patterns:
24: \Test{\normalizenumber{}}
25: \Test{\normalizenumber{--++}}
26: \Test{\normalizenumber{--++}}
27: \Test{\normalizenumber{-1.}}
28: \Test{\normalizenumber{3.7.0000 }}
29: \Test{\normalizenumber{8,5,0000 }}
30: \Test{\normalizenumber{8,9.0000 }}
31: \Test{\normalizenumber{9.3,0000 }}
32: \Test{\normalizenumber{A.0000}}
33: \Test{\normalizenumber{1{1}1}}
34: \Test{\normalizenumber{{1},6}}
35: \Test{\normalizenumber{1,}}
36: \Test{\normalizenumber{7,~ / 8()}}
37: \Test{\normalizenumber{1{1}1}}
\kern\dp\strutbox
\hrule
\kern\dp\strutbox
\verb|\def\macroa#1#2{- - + -00012\macrob}%|
\def\macroa#1#2{- - + -00012\macrob}%
\verb|\def\macrob{34.56000}%|
\def\macrob{34.56000}%
\verb|\normalizenumberexpandargfalse|
\normalizenumberexpandargfalse
32: \Test{\normalizenumber{\macroa{7}{8}}}
\verb|\normalizenumberexpandargtrue|
\normalizenumberexpandargtrue
33: \Test{\normalizenumber{\macroa{7}{8}}}
\end{document}