Check whether String represents valid number for PGF
I am searching for a reliable way to determine whether a String can be fed into pgfmathprintnumber
. I used to use the IfDecimal
from the xstring
package which works fine for things like 3.14
and similar inputs. However pgfmathprintnumber
can deal with scientific notation that will be sorted out by IfDecimal
because it thinks that it is not a number.
Here's an MWE:
documentclass{article}
usepackage{pgf}
usepackage{xstring}
begin{document}
deftestNum{3E+64}
IfDecimal{testNum}{
pgfmathprintnumber[sci]{testNum} is a number
}{
pgfmathprintnumber[sci]{testNum} is not a number
}
end{document}
As you'll see the number is properly recognized by pgfmathprintnumber
but not by IfDecimal
.
(I also tried the DTLisnumerical
command from the datatool
package but it doesn't work either).
Does someone know a macro that will also detect scientific notations as numbers (preferably a validation by PGF itself - something that will try to parse the string with the mathematical engine but simply exits if the string can't be parsed as a number instead of killing LaTeX with an error)?
tikz-pgf pgfmath parsing
add a comment |
I am searching for a reliable way to determine whether a String can be fed into pgfmathprintnumber
. I used to use the IfDecimal
from the xstring
package which works fine for things like 3.14
and similar inputs. However pgfmathprintnumber
can deal with scientific notation that will be sorted out by IfDecimal
because it thinks that it is not a number.
Here's an MWE:
documentclass{article}
usepackage{pgf}
usepackage{xstring}
begin{document}
deftestNum{3E+64}
IfDecimal{testNum}{
pgfmathprintnumber[sci]{testNum} is a number
}{
pgfmathprintnumber[sci]{testNum} is not a number
}
end{document}
As you'll see the number is properly recognized by pgfmathprintnumber
but not by IfDecimal
.
(I also tried the DTLisnumerical
command from the datatool
package but it doesn't work either).
Does someone know a macro that will also detect scientific notations as numbers (preferably a validation by PGF itself - something that will try to parse the string with the mathematical engine but simply exits if the string can't be parsed as a number instead of killing LaTeX with an error)?
tikz-pgf pgfmath parsing
add a comment |
I am searching for a reliable way to determine whether a String can be fed into pgfmathprintnumber
. I used to use the IfDecimal
from the xstring
package which works fine for things like 3.14
and similar inputs. However pgfmathprintnumber
can deal with scientific notation that will be sorted out by IfDecimal
because it thinks that it is not a number.
Here's an MWE:
documentclass{article}
usepackage{pgf}
usepackage{xstring}
begin{document}
deftestNum{3E+64}
IfDecimal{testNum}{
pgfmathprintnumber[sci]{testNum} is a number
}{
pgfmathprintnumber[sci]{testNum} is not a number
}
end{document}
As you'll see the number is properly recognized by pgfmathprintnumber
but not by IfDecimal
.
(I also tried the DTLisnumerical
command from the datatool
package but it doesn't work either).
Does someone know a macro that will also detect scientific notations as numbers (preferably a validation by PGF itself - something that will try to parse the string with the mathematical engine but simply exits if the string can't be parsed as a number instead of killing LaTeX with an error)?
tikz-pgf pgfmath parsing
I am searching for a reliable way to determine whether a String can be fed into pgfmathprintnumber
. I used to use the IfDecimal
from the xstring
package which works fine for things like 3.14
and similar inputs. However pgfmathprintnumber
can deal with scientific notation that will be sorted out by IfDecimal
because it thinks that it is not a number.
Here's an MWE:
documentclass{article}
usepackage{pgf}
usepackage{xstring}
begin{document}
deftestNum{3E+64}
IfDecimal{testNum}{
pgfmathprintnumber[sci]{testNum} is a number
}{
pgfmathprintnumber[sci]{testNum} is not a number
}
end{document}
As you'll see the number is properly recognized by pgfmathprintnumber
but not by IfDecimal
.
(I also tried the DTLisnumerical
command from the datatool
package but it doesn't work either).
Does someone know a macro that will also detect scientific notations as numbers (preferably a validation by PGF itself - something that will try to parse the string with the mathematical engine but simply exits if the string can't be parsed as a number instead of killing LaTeX with an error)?
tikz-pgf pgfmath parsing
tikz-pgf pgfmath parsing
asked Dec 8 at 13:40
Raven
784111
784111
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
Okay so I did some extensive web-research and stumbled upon this question which had an interesting approach in the last answer. Furthermore I found this post.
As can be seen in the first linked question there is a key /pgf/fpu/handlers/invalid number/.code
that defines the behaviour if a bad number format in pgfmathfloatparsenumber
is encountered. To quote the manual:
This command key is invoked in case an invalid string is parsed inside
of pgfmathfloatparsenumber. You can overwrite it to assign a
replacement pgfmathresult (in float!). The initial setting is to
generate an error message.
From the second question I found out that there are flags indicating whether the parsed number was valid or not. So I combined the two of them to get
documentclass{article}
usepackage{pgf}
usepgflibrary{fpu}
newcommand{isPGFNumber}[3]{% isPGFNumber{<Number>}{<True>}{<False>}
begingroup
pgfkeys{/pgf/fpu/handlers/invalid number/.code={}}%
pgfmathfloatparsenumber{#1}%
globalpgfmathfloatgetflagstomacropgfmathresultpgfFloatParseFlag%
endgroup
ifnumpgfFloatParseFlag=3%
#3%
else%
#2%
fi%
}
begin{document}
isPGFNumber{3}{T}{F}\
isPGFNumber{3.23}{T}{F}\
isPGFNumber{.3}{T}{F}\
isPGFNumber{3E+12}{T}{F}\
isPGFNumber{3e-8}{T}{F}\
isPGFNumber{3z}{T}{F}\
isPGFNumber{Is there a problem?}{T}{F}\\
%pgfmathfloatparsenumber{z}
end{document}
The begingroup
and endgroup
inside the macro definition is there in order to go back to the normal error-on-invalid-numbers-behaviour after having called the macro (Which can be tested by uncommenting the last statement in the document). As you can see it properly deals with the numbers even if provided in scientific format.
add a comment |
You can do it with regular expressions.
documentclass{article}
usepackage{xparse}
usepackage{siunitx} % for the test
ExplSyntaxOn
prg_new_protected_conditional:Nnn raven_if_fpnumber:n { T,F,TF }
{
regex_match:nnTF { [eE] } { #1 }
{% there is e or E
regex_match:nnTF
{
% optional sign,
% optional integer part,
% optional period,
% optional fractional part,
% one e or E
% optional sign
% mandatory integer
A
[-+]?([0-9]+(.[0-9]+)?|.[0-9]+)
[eE]{1}
[-+]?[0-9]+
Z
}
{ #1 } { prg_return_true: } { prg_return_false: }
}
{% no e nor E
regex_match:nnTF
{
A
[-+]?([0-9]+(.[0-9]+)?|.[0-9]+)
Z
}
{ #1 } { prg_return_true: } { prg_return_false: }
}
}
prg_generate_conditional_variant:Nnn raven_if_fpnumber:n { x } { T,F,TF }
NewDocumentCommand{isfpnumberTF}{mmm}
{
raven_if_fpnumber:xTF { #1 } { #2 } { #3 }
}
ExplSyntaxOff
% for the test
newcommand{test}[1]{%
texttt{detokenizeexpandafter{#1}}:
isfpnumberTF{#1}{num{#1}}{``#1'' is not a number}%
}
newcommand{anumber}{3E+64}
begin{document}
test{anumber}
test{3}
test{3.23}
test{.3}
test{3E+12}
test{3e-8}
test{3z}
test{Is there a problem?}
end{document}
add a comment |
The following builds upon tests I've implemented elsewhere. I did not remove everything unnecessary for this answer to work, so it might add more stuff than necessary. The test for a group in the argument is from Check for group as argument (expandable).
The test should be fully expandable.
documentclass{article}
makeatletter
defendMYifargument{endMYifargument}
newcommandMYif@endMYifargument[1]% >>>
{%
ifxendMYifargument#1%
MYif@fiAa
else
MYif@fiBb
fi
}% <<<
% MYif@fi macros >>>
longdefMYif@fiAa#1fi#2#3{fi#2}
longdefMYif@fiAb#1fi#2#3{fi#3}
longdefMYif@fiBafi#1#2{fi#1}
longdefMYif@fiBbfi#1#2{fi#2}
longdefMYif@fiAy#1fi#2{fi#2}
longdefMYif@fiAn#1fi#2{fi}
longdefMYif@fiByfi#1{fi#1}
longdefMYif@fiBnfi#1{fi}
longdefMYif@fifiAa#1fifi#2#3{fi#2}
longdefMYif@fifiAb#1fifi#2#3{fi#3}
longdefMYif@fifiBAa#1fifi#2#3{fifi#2}
longdefMYif@fifiBAb#1fifi#2#3{fifi#3}
longdefMYif@fifiBBafifi#1#2{fifi#1}
longdefMYif@fifiBBbfifi#1#2{fifi#2}
% <<<
newcommand*MYif@groupify@TF[1]% >>>
{%
expandafterlongexpandafteredefcsname MYif#1GTFendcsname##1%
{%
unexpanded{MYifGroupTF}{##1}%
{unexpandedexpandafter{csname MYif#1GTFendcsname}##1}%
{unexpandedexpandafter{csname MYif#1TFendcsname}{##1}}%
}%
}% <<<
newcommand*MYif@create@TandF[1]% >>>
{%
expandafterlongexpandafteredefcsname MYif#1Tendcsname##1%
{%
unexpandedexpandafter{csname MYif#1TFendcsname}{##1}%
{noexpand@firstofone}
{noexpand@gobble}%
}%
expandafterlongexpandafteredefcsname MYif#1Fendcsname##1%
{%
unexpandedexpandafter{csname MYif#1TFendcsname}{##1}%
{noexpand@gobble}
{noexpand@firstofone}%
}%
}% <<<
newcommand*MYif@create@TandF@twoargs[1]% >>>
{%
expandafterlongexpandafteredefcsname MYif#1Tendcsname##1##2%
{%
unexpandedexpandafter{csname MYif#1TFendcsname}{##1}{##2}%
{noexpand@firstofone}
{noexpand@gobble}%
}%
expandafterlongexpandafteredefcsname MYif#1Fendcsname##1##2%
{%
unexpandedexpandafter{csname MYif#1TFendcsname}{##1}{##2}%
{noexpand@gobble}
{noexpand@firstofone}%
}%
}% <<<
newcommand*MYif@create@N@TandF[1]% >>>
{%
expandafterlongexpandafteredefcsname MYif#1NTFendcsname##1%
{%
noexpandexpandafter
expandafternoexpandcsname MYif#1TFendcsname
noexpandexpandafter{##1}%
}%
MYif@create@TandF{#1N}%
}% <<<
newcommand*MYif@create@N@TandF@twoargs[1]% >>>
{%
expandafterlongexpandafteredefcsname MYif#1NNTFendcsname##1##2%
{%
noexpandexpandafter
expandafternoexpandcsname MYif#1NNTF@aendcsname
noexpandexpandafter{##2}{##1}%
}%
expandafterlongexpandafteredefcsname MYif#1NNTF@aendcsname##1##2%
{%
noexpandexpandafter
expandafternoexpandcsname MYif#1TFendcsname
noexpandexpandafter{##2}{##1}%
}%
MYif@create@TandF@twoargs{#1NN}%
expandafterlongexpandafteredefcsname MYif#1NnTFendcsname##1##2%
{%
noexpandexpandafter
expandafternoexpandcsname MYif#1TFendcsname
noexpandexpandafter{##1}{##2}%
}%
MYif@create@TandF@twoargs{#1Nn}%
expandafterlongexpandafteredefcsname MYif#1nNTFendcsname##1##2%
{%
noexpandexpandafter
expandafternoexpandcsname MYif#1nNTF@aendcsname
noexpandexpandafter{##2}{##1}%
}%
expandafterlongexpandafteredefcsname MYif#1nNTF@aendcsname##1##2%
{%
expandafternoexpandcsname MYif#1TFendcsname{##2}{##1}
}%
MYif@create@TandF@twoargs{#1nN}%
}% <<<
newcommand*MYif@create@TandF@N@TandF[1]% >>>
{%
MYif@create@TandF{#1}%
MYif@create@N@TandF{#1}%
}% <<<
newcommand*MYif@create@TandF@N@TandF@twoargs[1]% >>>
{%
MYif@create@TandF@twoargs{#1}%
MYif@create@N@TandF@twoargs{#1}%
}% <<<
newcommandMYif@notEmpty@noGroup@noSpace[2]% >>>
{%
MYifEmptyTF{#1}
{@secondoftwo}
{%
MYifContainsGroupTF{#1}
{@secondoftwo}
{%
MYifContainsSpaceTF{#1}
{@secondoftwo}
{#2}%
}%
}%
}% <<<
% MYifEmpty >>>
newcommandMYifEmptyTF[1]% >>>
{%
ifrelaxdetokenize{#1}relax
MYif@fiAa
else
MYif@fiBb
fi
}% <<<
newcommandMYifEmptyT[1]{% >>>
ifrelaxdetokenize{#1}relax
MYif@fiAy
else
MYif@fiBn
fi}
% <<<
newcommandMYifEmptyF[1]{% >>>
ifrelaxdetokenize{#1}relax
MYif@fiAn
else
MYif@fiBy
fi}
% <<<
newcommandMYifEmptyNTF[1]% >>>
{expandafterMYifEmptyTFexpandafter{#1}}% <<<
newcommandMYifEmptyNT[1]% >>>
{expandafterMYifEmptyTexpandafter{#1}}% <<<
newcommandMYifEmptyNF[1]% >>>
{expandafterMYifEmptyFexpandafter{#1}}% <<<
MYif@groupify@TF{Empty}
MYif@create@TandF@N@TandF{EmptyG}
% <<<
% MYifContainsGroup >>>
newcommandMYifContainsGroupTF[1]% >>>
{%
expandafterMYifContainsGroup@a
MYifContainsGroup@eat#1{}%
MYifContainsGroup@endargument
}% <<<
longdefMYifContainsGroup@eat#1#{}
longdefMYifContainsGroup@a#1MYifContainsGroup@endargument% >>>
{%
MYifEmptyTF{#1}
{@secondoftwo}
{@firstoftwo}%
}% <<<
MYif@groupify@TF{ContainsGroup}
MYif@create@TandF@N@TandF{ContainsGroup}
MYif@create@TandF@N@TandF{ContainsGroupG}
% <<<
% MYifContainsSpace >>>
newcommandMYifContainsSpaceTF[1]% >>>
{%
expandafterMYifContainsSpace@a
MYifContainsSpace@eat#1
MYifContainsSpace@endargument
}% <<<
longdefMYifContainsSpace@a#1MYifContainsSpace@endargument% >>>
{%
MYifEmptyTF{#1}
{@secondoftwo}
{@firstoftwo}%
}% <<<
longdefMYifContainsSpace@eat#1 {}
MYif@groupify@TF{ContainsSpace}
MYif@create@TandF@N@TandF{ContainsSpace}
MYif@create@TandF@N@TandF{ContainsSpaceG}
% <<<
% MYifDigit >>>
newcommandMYifDigitTF[1]% >>>
{%
MYifOneTokenNoGroupTF{#1}
{MYifDigit@a{#1}}
{@secondoftwo}%
}% <<<
newcommandMYifDigit@a[1]% >>>
{%
ifx0#1MYif@fiAa
elseMYifDigit@b1#1%
elseMYifDigit@b2#1%
elseMYifDigit@b3#1%
elseMYifDigit@b4#1%
elseMYifDigit@b5#1%
elseMYifDigit@b6#1%
elseMYifDigit@b7#1%
elseMYifDigit@b8#1%
elseMYifDigit@b9#1%
elseMYif@fiBb
fi
}% <<<
newcommandMYifDigit@b[2]% >>>
{%
fiifx#1#2MYif@fiAa
}% <<<
newcommandMYifDigitGTF[1]% >>>
{%
MYifGroupTF{#1}
{MYifDigitGTF#1}
{%
MYifOneTokenTF{#1}
{MYifDigit@a{#1}}
{@secondoftwo}%
}%
}% <<<
MYif@create@TandF@N@TandF{Digit}
MYif@create@TandF@N@TandF{DigitG}
% <<<
% MYifNumber >>>
newcommandMYifNumberTF[1]% >>>
{%
MYif@notEmpty@noGroup@noSpace{#1}{MYifNumber@ifSign#1endMYifargument}%
}% <<<
newcommandMYifNumber@ifSign[1]% >>>
{%
ifx+#1%
MYif@fifiAa
else
ifx-#1%
MYif@fifiBAa
else
MYif@fifiBBb
fi
fi
{MYifNumber@ifDigit@noend}
{MYifNumber@ifDigit#1}
}% <<<
newcommandMYifNumber@ifDigit[1]% >>>
{%
MYif@endMYifargument{#1}
{@firstoftwo}
{%
MYifDigit@a{#1}
{MYifNumber@ifDigit}
{MYifNumber@false}%
}%
}% <<<
newcommandMYifNumber@ifDigit@noend[1]% >>>
{%
MYif@endMYifargument{#1}
{@secondoftwo}
{%
MYifDigit@a{#1}
{MYifNumber@ifDigit}
{MYifNumber@false}%
}%
}% <<<
longdefMYifNumber@false#1endMYifargument% >>>
{%
@secondoftwo
}% <<<
MYif@groupify@TF{Number}
MYif@create@TandF@N@TandF{Number}
MYif@create@TandF@N@TandF{NumberG}
% <<<
% MYifFloat >>>
newcommandMYifFloatTF[1]% >>>
{%
MYif@notEmpty@noGroup@noSpace{#1}{MYifFloat@a{#1}}
}% <<<
%newcommandMYifFloat@a newcommandMYifFloat@ifDot >>>
begingroup
catcode`?=4
defMYif@zz
{%
endgroup
newcommandMYifFloat@a[1]% >>>
{%
MYifFloat@ifDot{##1}
{MYifFloat@withDot##1MYifFloat@endargument}
{MYifNumber@ifSign##1endMYifargument}%
}% <<<
newcommandMYifFloat@ifDot[1]% >>>
{%
MYifFloat@ifDot@a##1.?MYifFloat@endargument
}% <<<
longdefMYifFloat@ifDot@a##1.##2MYifFloat@endargument% >>>
{%
ifx?##2%
MYif@fiAb
else
MYif@fiBa
fi
}% <<<
}
MYif@zz
% <<<
longdefMYifFloat@withDot#1.#2MYifFloat@endargument% >>>
{%
MYifEmptyTF{#1}
{MYifNumber@ifDigit@noend#2endMYifargument}
{%
MYifNumber@ifSign#1endMYifargument
{MYifNumber@ifDigit#2endMYifargument}
{@secondoftwo}%
}%
}% <<<
MYif@groupify@TF{Float}
MYif@create@TandF@N@TandF{Float}
MYif@create@TandF@N@TandF{FloatG}
% <<<
% MYifContainsE >>>
newcommandMYifContainseTF[1]% >>>
{%
MYifContainsE@e#1eMYifContainsE@end
{@secondoftwo}
{@firstoftwo}%
}% <<<
longdefMYifContainsE@e#1e#2MYifContainsE@end% >>>
{%
MYifEmptyTF{#2}%
}% <<<
newcommandMYifContainsETF[1]% >>>
{%
MYifContainsE@E#1EMYifContainsE@end
{@secondoftwo}
{@firstoftwo}%
}% <<<
longdefMYifContainsE@E#1E#2MYifContainsE@end% >>>
{%
MYifEmptyTF{#2}%
}% <<<
% <<<
% MYifScientific >>>
newcommandMYifScientificTF[1]% >>>
{%
MYifContainsETF{#1}
{MYifScientific@withE#1endMYifScientific}
{%
MYifContainseTF{#1}
{MYifScientific@withe#1endMYifScientific}
{MYifFloatTF{#1}}%
}%
}% <<<
longdefMYifScientific@withE#1E#2endMYifScientific% >>>
{%
MYifFloatTF{#1}
{MYifNumberTF{#2}}
{@secondoftwo}%
}% <<<
longdefMYifScientific@withe#1e#2endMYifScientific% >>>
{%
MYifFloatTF{#1}
{MYifNumberTF{#2}}
{@secondoftwo}%
}% <<<
MYif@groupify@TF{Scientific}
MYif@create@TandF@N@TandF{Scientific}
MYif@create@TandF@N@TandF{ScientificG}
% <<<
makeatother
usepackage{pgf}
begin{document}
deftestNum{3e+64}
MYifScientificNTF{testNum}
{%
pgfmathprintnumber[sci]{testNum} is a number
}
{%
pgfmathprintnumber[sci]{testNum} is not a number
}
end{document}
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "85"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f463814%2fcheck-whether-string-represents-valid-number-for-pgf%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
Okay so I did some extensive web-research and stumbled upon this question which had an interesting approach in the last answer. Furthermore I found this post.
As can be seen in the first linked question there is a key /pgf/fpu/handlers/invalid number/.code
that defines the behaviour if a bad number format in pgfmathfloatparsenumber
is encountered. To quote the manual:
This command key is invoked in case an invalid string is parsed inside
of pgfmathfloatparsenumber. You can overwrite it to assign a
replacement pgfmathresult (in float!). The initial setting is to
generate an error message.
From the second question I found out that there are flags indicating whether the parsed number was valid or not. So I combined the two of them to get
documentclass{article}
usepackage{pgf}
usepgflibrary{fpu}
newcommand{isPGFNumber}[3]{% isPGFNumber{<Number>}{<True>}{<False>}
begingroup
pgfkeys{/pgf/fpu/handlers/invalid number/.code={}}%
pgfmathfloatparsenumber{#1}%
globalpgfmathfloatgetflagstomacropgfmathresultpgfFloatParseFlag%
endgroup
ifnumpgfFloatParseFlag=3%
#3%
else%
#2%
fi%
}
begin{document}
isPGFNumber{3}{T}{F}\
isPGFNumber{3.23}{T}{F}\
isPGFNumber{.3}{T}{F}\
isPGFNumber{3E+12}{T}{F}\
isPGFNumber{3e-8}{T}{F}\
isPGFNumber{3z}{T}{F}\
isPGFNumber{Is there a problem?}{T}{F}\\
%pgfmathfloatparsenumber{z}
end{document}
The begingroup
and endgroup
inside the macro definition is there in order to go back to the normal error-on-invalid-numbers-behaviour after having called the macro (Which can be tested by uncommenting the last statement in the document). As you can see it properly deals with the numbers even if provided in scientific format.
add a comment |
Okay so I did some extensive web-research and stumbled upon this question which had an interesting approach in the last answer. Furthermore I found this post.
As can be seen in the first linked question there is a key /pgf/fpu/handlers/invalid number/.code
that defines the behaviour if a bad number format in pgfmathfloatparsenumber
is encountered. To quote the manual:
This command key is invoked in case an invalid string is parsed inside
of pgfmathfloatparsenumber. You can overwrite it to assign a
replacement pgfmathresult (in float!). The initial setting is to
generate an error message.
From the second question I found out that there are flags indicating whether the parsed number was valid or not. So I combined the two of them to get
documentclass{article}
usepackage{pgf}
usepgflibrary{fpu}
newcommand{isPGFNumber}[3]{% isPGFNumber{<Number>}{<True>}{<False>}
begingroup
pgfkeys{/pgf/fpu/handlers/invalid number/.code={}}%
pgfmathfloatparsenumber{#1}%
globalpgfmathfloatgetflagstomacropgfmathresultpgfFloatParseFlag%
endgroup
ifnumpgfFloatParseFlag=3%
#3%
else%
#2%
fi%
}
begin{document}
isPGFNumber{3}{T}{F}\
isPGFNumber{3.23}{T}{F}\
isPGFNumber{.3}{T}{F}\
isPGFNumber{3E+12}{T}{F}\
isPGFNumber{3e-8}{T}{F}\
isPGFNumber{3z}{T}{F}\
isPGFNumber{Is there a problem?}{T}{F}\\
%pgfmathfloatparsenumber{z}
end{document}
The begingroup
and endgroup
inside the macro definition is there in order to go back to the normal error-on-invalid-numbers-behaviour after having called the macro (Which can be tested by uncommenting the last statement in the document). As you can see it properly deals with the numbers even if provided in scientific format.
add a comment |
Okay so I did some extensive web-research and stumbled upon this question which had an interesting approach in the last answer. Furthermore I found this post.
As can be seen in the first linked question there is a key /pgf/fpu/handlers/invalid number/.code
that defines the behaviour if a bad number format in pgfmathfloatparsenumber
is encountered. To quote the manual:
This command key is invoked in case an invalid string is parsed inside
of pgfmathfloatparsenumber. You can overwrite it to assign a
replacement pgfmathresult (in float!). The initial setting is to
generate an error message.
From the second question I found out that there are flags indicating whether the parsed number was valid or not. So I combined the two of them to get
documentclass{article}
usepackage{pgf}
usepgflibrary{fpu}
newcommand{isPGFNumber}[3]{% isPGFNumber{<Number>}{<True>}{<False>}
begingroup
pgfkeys{/pgf/fpu/handlers/invalid number/.code={}}%
pgfmathfloatparsenumber{#1}%
globalpgfmathfloatgetflagstomacropgfmathresultpgfFloatParseFlag%
endgroup
ifnumpgfFloatParseFlag=3%
#3%
else%
#2%
fi%
}
begin{document}
isPGFNumber{3}{T}{F}\
isPGFNumber{3.23}{T}{F}\
isPGFNumber{.3}{T}{F}\
isPGFNumber{3E+12}{T}{F}\
isPGFNumber{3e-8}{T}{F}\
isPGFNumber{3z}{T}{F}\
isPGFNumber{Is there a problem?}{T}{F}\\
%pgfmathfloatparsenumber{z}
end{document}
The begingroup
and endgroup
inside the macro definition is there in order to go back to the normal error-on-invalid-numbers-behaviour after having called the macro (Which can be tested by uncommenting the last statement in the document). As you can see it properly deals with the numbers even if provided in scientific format.
Okay so I did some extensive web-research and stumbled upon this question which had an interesting approach in the last answer. Furthermore I found this post.
As can be seen in the first linked question there is a key /pgf/fpu/handlers/invalid number/.code
that defines the behaviour if a bad number format in pgfmathfloatparsenumber
is encountered. To quote the manual:
This command key is invoked in case an invalid string is parsed inside
of pgfmathfloatparsenumber. You can overwrite it to assign a
replacement pgfmathresult (in float!). The initial setting is to
generate an error message.
From the second question I found out that there are flags indicating whether the parsed number was valid or not. So I combined the two of them to get
documentclass{article}
usepackage{pgf}
usepgflibrary{fpu}
newcommand{isPGFNumber}[3]{% isPGFNumber{<Number>}{<True>}{<False>}
begingroup
pgfkeys{/pgf/fpu/handlers/invalid number/.code={}}%
pgfmathfloatparsenumber{#1}%
globalpgfmathfloatgetflagstomacropgfmathresultpgfFloatParseFlag%
endgroup
ifnumpgfFloatParseFlag=3%
#3%
else%
#2%
fi%
}
begin{document}
isPGFNumber{3}{T}{F}\
isPGFNumber{3.23}{T}{F}\
isPGFNumber{.3}{T}{F}\
isPGFNumber{3E+12}{T}{F}\
isPGFNumber{3e-8}{T}{F}\
isPGFNumber{3z}{T}{F}\
isPGFNumber{Is there a problem?}{T}{F}\\
%pgfmathfloatparsenumber{z}
end{document}
The begingroup
and endgroup
inside the macro definition is there in order to go back to the normal error-on-invalid-numbers-behaviour after having called the macro (Which can be tested by uncommenting the last statement in the document). As you can see it properly deals with the numbers even if provided in scientific format.
edited Dec 8 at 14:37
answered Dec 8 at 14:12
Raven
784111
784111
add a comment |
add a comment |
You can do it with regular expressions.
documentclass{article}
usepackage{xparse}
usepackage{siunitx} % for the test
ExplSyntaxOn
prg_new_protected_conditional:Nnn raven_if_fpnumber:n { T,F,TF }
{
regex_match:nnTF { [eE] } { #1 }
{% there is e or E
regex_match:nnTF
{
% optional sign,
% optional integer part,
% optional period,
% optional fractional part,
% one e or E
% optional sign
% mandatory integer
A
[-+]?([0-9]+(.[0-9]+)?|.[0-9]+)
[eE]{1}
[-+]?[0-9]+
Z
}
{ #1 } { prg_return_true: } { prg_return_false: }
}
{% no e nor E
regex_match:nnTF
{
A
[-+]?([0-9]+(.[0-9]+)?|.[0-9]+)
Z
}
{ #1 } { prg_return_true: } { prg_return_false: }
}
}
prg_generate_conditional_variant:Nnn raven_if_fpnumber:n { x } { T,F,TF }
NewDocumentCommand{isfpnumberTF}{mmm}
{
raven_if_fpnumber:xTF { #1 } { #2 } { #3 }
}
ExplSyntaxOff
% for the test
newcommand{test}[1]{%
texttt{detokenizeexpandafter{#1}}:
isfpnumberTF{#1}{num{#1}}{``#1'' is not a number}%
}
newcommand{anumber}{3E+64}
begin{document}
test{anumber}
test{3}
test{3.23}
test{.3}
test{3E+12}
test{3e-8}
test{3z}
test{Is there a problem?}
end{document}
add a comment |
You can do it with regular expressions.
documentclass{article}
usepackage{xparse}
usepackage{siunitx} % for the test
ExplSyntaxOn
prg_new_protected_conditional:Nnn raven_if_fpnumber:n { T,F,TF }
{
regex_match:nnTF { [eE] } { #1 }
{% there is e or E
regex_match:nnTF
{
% optional sign,
% optional integer part,
% optional period,
% optional fractional part,
% one e or E
% optional sign
% mandatory integer
A
[-+]?([0-9]+(.[0-9]+)?|.[0-9]+)
[eE]{1}
[-+]?[0-9]+
Z
}
{ #1 } { prg_return_true: } { prg_return_false: }
}
{% no e nor E
regex_match:nnTF
{
A
[-+]?([0-9]+(.[0-9]+)?|.[0-9]+)
Z
}
{ #1 } { prg_return_true: } { prg_return_false: }
}
}
prg_generate_conditional_variant:Nnn raven_if_fpnumber:n { x } { T,F,TF }
NewDocumentCommand{isfpnumberTF}{mmm}
{
raven_if_fpnumber:xTF { #1 } { #2 } { #3 }
}
ExplSyntaxOff
% for the test
newcommand{test}[1]{%
texttt{detokenizeexpandafter{#1}}:
isfpnumberTF{#1}{num{#1}}{``#1'' is not a number}%
}
newcommand{anumber}{3E+64}
begin{document}
test{anumber}
test{3}
test{3.23}
test{.3}
test{3E+12}
test{3e-8}
test{3z}
test{Is there a problem?}
end{document}
add a comment |
You can do it with regular expressions.
documentclass{article}
usepackage{xparse}
usepackage{siunitx} % for the test
ExplSyntaxOn
prg_new_protected_conditional:Nnn raven_if_fpnumber:n { T,F,TF }
{
regex_match:nnTF { [eE] } { #1 }
{% there is e or E
regex_match:nnTF
{
% optional sign,
% optional integer part,
% optional period,
% optional fractional part,
% one e or E
% optional sign
% mandatory integer
A
[-+]?([0-9]+(.[0-9]+)?|.[0-9]+)
[eE]{1}
[-+]?[0-9]+
Z
}
{ #1 } { prg_return_true: } { prg_return_false: }
}
{% no e nor E
regex_match:nnTF
{
A
[-+]?([0-9]+(.[0-9]+)?|.[0-9]+)
Z
}
{ #1 } { prg_return_true: } { prg_return_false: }
}
}
prg_generate_conditional_variant:Nnn raven_if_fpnumber:n { x } { T,F,TF }
NewDocumentCommand{isfpnumberTF}{mmm}
{
raven_if_fpnumber:xTF { #1 } { #2 } { #3 }
}
ExplSyntaxOff
% for the test
newcommand{test}[1]{%
texttt{detokenizeexpandafter{#1}}:
isfpnumberTF{#1}{num{#1}}{``#1'' is not a number}%
}
newcommand{anumber}{3E+64}
begin{document}
test{anumber}
test{3}
test{3.23}
test{.3}
test{3E+12}
test{3e-8}
test{3z}
test{Is there a problem?}
end{document}
You can do it with regular expressions.
documentclass{article}
usepackage{xparse}
usepackage{siunitx} % for the test
ExplSyntaxOn
prg_new_protected_conditional:Nnn raven_if_fpnumber:n { T,F,TF }
{
regex_match:nnTF { [eE] } { #1 }
{% there is e or E
regex_match:nnTF
{
% optional sign,
% optional integer part,
% optional period,
% optional fractional part,
% one e or E
% optional sign
% mandatory integer
A
[-+]?([0-9]+(.[0-9]+)?|.[0-9]+)
[eE]{1}
[-+]?[0-9]+
Z
}
{ #1 } { prg_return_true: } { prg_return_false: }
}
{% no e nor E
regex_match:nnTF
{
A
[-+]?([0-9]+(.[0-9]+)?|.[0-9]+)
Z
}
{ #1 } { prg_return_true: } { prg_return_false: }
}
}
prg_generate_conditional_variant:Nnn raven_if_fpnumber:n { x } { T,F,TF }
NewDocumentCommand{isfpnumberTF}{mmm}
{
raven_if_fpnumber:xTF { #1 } { #2 } { #3 }
}
ExplSyntaxOff
% for the test
newcommand{test}[1]{%
texttt{detokenizeexpandafter{#1}}:
isfpnumberTF{#1}{num{#1}}{``#1'' is not a number}%
}
newcommand{anumber}{3E+64}
begin{document}
test{anumber}
test{3}
test{3.23}
test{.3}
test{3E+12}
test{3e-8}
test{3z}
test{Is there a problem?}
end{document}
answered Dec 8 at 21:07
egreg
706k8618773159
706k8618773159
add a comment |
add a comment |
The following builds upon tests I've implemented elsewhere. I did not remove everything unnecessary for this answer to work, so it might add more stuff than necessary. The test for a group in the argument is from Check for group as argument (expandable).
The test should be fully expandable.
documentclass{article}
makeatletter
defendMYifargument{endMYifargument}
newcommandMYif@endMYifargument[1]% >>>
{%
ifxendMYifargument#1%
MYif@fiAa
else
MYif@fiBb
fi
}% <<<
% MYif@fi macros >>>
longdefMYif@fiAa#1fi#2#3{fi#2}
longdefMYif@fiAb#1fi#2#3{fi#3}
longdefMYif@fiBafi#1#2{fi#1}
longdefMYif@fiBbfi#1#2{fi#2}
longdefMYif@fiAy#1fi#2{fi#2}
longdefMYif@fiAn#1fi#2{fi}
longdefMYif@fiByfi#1{fi#1}
longdefMYif@fiBnfi#1{fi}
longdefMYif@fifiAa#1fifi#2#3{fi#2}
longdefMYif@fifiAb#1fifi#2#3{fi#3}
longdefMYif@fifiBAa#1fifi#2#3{fifi#2}
longdefMYif@fifiBAb#1fifi#2#3{fifi#3}
longdefMYif@fifiBBafifi#1#2{fifi#1}
longdefMYif@fifiBBbfifi#1#2{fifi#2}
% <<<
newcommand*MYif@groupify@TF[1]% >>>
{%
expandafterlongexpandafteredefcsname MYif#1GTFendcsname##1%
{%
unexpanded{MYifGroupTF}{##1}%
{unexpandedexpandafter{csname MYif#1GTFendcsname}##1}%
{unexpandedexpandafter{csname MYif#1TFendcsname}{##1}}%
}%
}% <<<
newcommand*MYif@create@TandF[1]% >>>
{%
expandafterlongexpandafteredefcsname MYif#1Tendcsname##1%
{%
unexpandedexpandafter{csname MYif#1TFendcsname}{##1}%
{noexpand@firstofone}
{noexpand@gobble}%
}%
expandafterlongexpandafteredefcsname MYif#1Fendcsname##1%
{%
unexpandedexpandafter{csname MYif#1TFendcsname}{##1}%
{noexpand@gobble}
{noexpand@firstofone}%
}%
}% <<<
newcommand*MYif@create@TandF@twoargs[1]% >>>
{%
expandafterlongexpandafteredefcsname MYif#1Tendcsname##1##2%
{%
unexpandedexpandafter{csname MYif#1TFendcsname}{##1}{##2}%
{noexpand@firstofone}
{noexpand@gobble}%
}%
expandafterlongexpandafteredefcsname MYif#1Fendcsname##1##2%
{%
unexpandedexpandafter{csname MYif#1TFendcsname}{##1}{##2}%
{noexpand@gobble}
{noexpand@firstofone}%
}%
}% <<<
newcommand*MYif@create@N@TandF[1]% >>>
{%
expandafterlongexpandafteredefcsname MYif#1NTFendcsname##1%
{%
noexpandexpandafter
expandafternoexpandcsname MYif#1TFendcsname
noexpandexpandafter{##1}%
}%
MYif@create@TandF{#1N}%
}% <<<
newcommand*MYif@create@N@TandF@twoargs[1]% >>>
{%
expandafterlongexpandafteredefcsname MYif#1NNTFendcsname##1##2%
{%
noexpandexpandafter
expandafternoexpandcsname MYif#1NNTF@aendcsname
noexpandexpandafter{##2}{##1}%
}%
expandafterlongexpandafteredefcsname MYif#1NNTF@aendcsname##1##2%
{%
noexpandexpandafter
expandafternoexpandcsname MYif#1TFendcsname
noexpandexpandafter{##2}{##1}%
}%
MYif@create@TandF@twoargs{#1NN}%
expandafterlongexpandafteredefcsname MYif#1NnTFendcsname##1##2%
{%
noexpandexpandafter
expandafternoexpandcsname MYif#1TFendcsname
noexpandexpandafter{##1}{##2}%
}%
MYif@create@TandF@twoargs{#1Nn}%
expandafterlongexpandafteredefcsname MYif#1nNTFendcsname##1##2%
{%
noexpandexpandafter
expandafternoexpandcsname MYif#1nNTF@aendcsname
noexpandexpandafter{##2}{##1}%
}%
expandafterlongexpandafteredefcsname MYif#1nNTF@aendcsname##1##2%
{%
expandafternoexpandcsname MYif#1TFendcsname{##2}{##1}
}%
MYif@create@TandF@twoargs{#1nN}%
}% <<<
newcommand*MYif@create@TandF@N@TandF[1]% >>>
{%
MYif@create@TandF{#1}%
MYif@create@N@TandF{#1}%
}% <<<
newcommand*MYif@create@TandF@N@TandF@twoargs[1]% >>>
{%
MYif@create@TandF@twoargs{#1}%
MYif@create@N@TandF@twoargs{#1}%
}% <<<
newcommandMYif@notEmpty@noGroup@noSpace[2]% >>>
{%
MYifEmptyTF{#1}
{@secondoftwo}
{%
MYifContainsGroupTF{#1}
{@secondoftwo}
{%
MYifContainsSpaceTF{#1}
{@secondoftwo}
{#2}%
}%
}%
}% <<<
% MYifEmpty >>>
newcommandMYifEmptyTF[1]% >>>
{%
ifrelaxdetokenize{#1}relax
MYif@fiAa
else
MYif@fiBb
fi
}% <<<
newcommandMYifEmptyT[1]{% >>>
ifrelaxdetokenize{#1}relax
MYif@fiAy
else
MYif@fiBn
fi}
% <<<
newcommandMYifEmptyF[1]{% >>>
ifrelaxdetokenize{#1}relax
MYif@fiAn
else
MYif@fiBy
fi}
% <<<
newcommandMYifEmptyNTF[1]% >>>
{expandafterMYifEmptyTFexpandafter{#1}}% <<<
newcommandMYifEmptyNT[1]% >>>
{expandafterMYifEmptyTexpandafter{#1}}% <<<
newcommandMYifEmptyNF[1]% >>>
{expandafterMYifEmptyFexpandafter{#1}}% <<<
MYif@groupify@TF{Empty}
MYif@create@TandF@N@TandF{EmptyG}
% <<<
% MYifContainsGroup >>>
newcommandMYifContainsGroupTF[1]% >>>
{%
expandafterMYifContainsGroup@a
MYifContainsGroup@eat#1{}%
MYifContainsGroup@endargument
}% <<<
longdefMYifContainsGroup@eat#1#{}
longdefMYifContainsGroup@a#1MYifContainsGroup@endargument% >>>
{%
MYifEmptyTF{#1}
{@secondoftwo}
{@firstoftwo}%
}% <<<
MYif@groupify@TF{ContainsGroup}
MYif@create@TandF@N@TandF{ContainsGroup}
MYif@create@TandF@N@TandF{ContainsGroupG}
% <<<
% MYifContainsSpace >>>
newcommandMYifContainsSpaceTF[1]% >>>
{%
expandafterMYifContainsSpace@a
MYifContainsSpace@eat#1
MYifContainsSpace@endargument
}% <<<
longdefMYifContainsSpace@a#1MYifContainsSpace@endargument% >>>
{%
MYifEmptyTF{#1}
{@secondoftwo}
{@firstoftwo}%
}% <<<
longdefMYifContainsSpace@eat#1 {}
MYif@groupify@TF{ContainsSpace}
MYif@create@TandF@N@TandF{ContainsSpace}
MYif@create@TandF@N@TandF{ContainsSpaceG}
% <<<
% MYifDigit >>>
newcommandMYifDigitTF[1]% >>>
{%
MYifOneTokenNoGroupTF{#1}
{MYifDigit@a{#1}}
{@secondoftwo}%
}% <<<
newcommandMYifDigit@a[1]% >>>
{%
ifx0#1MYif@fiAa
elseMYifDigit@b1#1%
elseMYifDigit@b2#1%
elseMYifDigit@b3#1%
elseMYifDigit@b4#1%
elseMYifDigit@b5#1%
elseMYifDigit@b6#1%
elseMYifDigit@b7#1%
elseMYifDigit@b8#1%
elseMYifDigit@b9#1%
elseMYif@fiBb
fi
}% <<<
newcommandMYifDigit@b[2]% >>>
{%
fiifx#1#2MYif@fiAa
}% <<<
newcommandMYifDigitGTF[1]% >>>
{%
MYifGroupTF{#1}
{MYifDigitGTF#1}
{%
MYifOneTokenTF{#1}
{MYifDigit@a{#1}}
{@secondoftwo}%
}%
}% <<<
MYif@create@TandF@N@TandF{Digit}
MYif@create@TandF@N@TandF{DigitG}
% <<<
% MYifNumber >>>
newcommandMYifNumberTF[1]% >>>
{%
MYif@notEmpty@noGroup@noSpace{#1}{MYifNumber@ifSign#1endMYifargument}%
}% <<<
newcommandMYifNumber@ifSign[1]% >>>
{%
ifx+#1%
MYif@fifiAa
else
ifx-#1%
MYif@fifiBAa
else
MYif@fifiBBb
fi
fi
{MYifNumber@ifDigit@noend}
{MYifNumber@ifDigit#1}
}% <<<
newcommandMYifNumber@ifDigit[1]% >>>
{%
MYif@endMYifargument{#1}
{@firstoftwo}
{%
MYifDigit@a{#1}
{MYifNumber@ifDigit}
{MYifNumber@false}%
}%
}% <<<
newcommandMYifNumber@ifDigit@noend[1]% >>>
{%
MYif@endMYifargument{#1}
{@secondoftwo}
{%
MYifDigit@a{#1}
{MYifNumber@ifDigit}
{MYifNumber@false}%
}%
}% <<<
longdefMYifNumber@false#1endMYifargument% >>>
{%
@secondoftwo
}% <<<
MYif@groupify@TF{Number}
MYif@create@TandF@N@TandF{Number}
MYif@create@TandF@N@TandF{NumberG}
% <<<
% MYifFloat >>>
newcommandMYifFloatTF[1]% >>>
{%
MYif@notEmpty@noGroup@noSpace{#1}{MYifFloat@a{#1}}
}% <<<
%newcommandMYifFloat@a newcommandMYifFloat@ifDot >>>
begingroup
catcode`?=4
defMYif@zz
{%
endgroup
newcommandMYifFloat@a[1]% >>>
{%
MYifFloat@ifDot{##1}
{MYifFloat@withDot##1MYifFloat@endargument}
{MYifNumber@ifSign##1endMYifargument}%
}% <<<
newcommandMYifFloat@ifDot[1]% >>>
{%
MYifFloat@ifDot@a##1.?MYifFloat@endargument
}% <<<
longdefMYifFloat@ifDot@a##1.##2MYifFloat@endargument% >>>
{%
ifx?##2%
MYif@fiAb
else
MYif@fiBa
fi
}% <<<
}
MYif@zz
% <<<
longdefMYifFloat@withDot#1.#2MYifFloat@endargument% >>>
{%
MYifEmptyTF{#1}
{MYifNumber@ifDigit@noend#2endMYifargument}
{%
MYifNumber@ifSign#1endMYifargument
{MYifNumber@ifDigit#2endMYifargument}
{@secondoftwo}%
}%
}% <<<
MYif@groupify@TF{Float}
MYif@create@TandF@N@TandF{Float}
MYif@create@TandF@N@TandF{FloatG}
% <<<
% MYifContainsE >>>
newcommandMYifContainseTF[1]% >>>
{%
MYifContainsE@e#1eMYifContainsE@end
{@secondoftwo}
{@firstoftwo}%
}% <<<
longdefMYifContainsE@e#1e#2MYifContainsE@end% >>>
{%
MYifEmptyTF{#2}%
}% <<<
newcommandMYifContainsETF[1]% >>>
{%
MYifContainsE@E#1EMYifContainsE@end
{@secondoftwo}
{@firstoftwo}%
}% <<<
longdefMYifContainsE@E#1E#2MYifContainsE@end% >>>
{%
MYifEmptyTF{#2}%
}% <<<
% <<<
% MYifScientific >>>
newcommandMYifScientificTF[1]% >>>
{%
MYifContainsETF{#1}
{MYifScientific@withE#1endMYifScientific}
{%
MYifContainseTF{#1}
{MYifScientific@withe#1endMYifScientific}
{MYifFloatTF{#1}}%
}%
}% <<<
longdefMYifScientific@withE#1E#2endMYifScientific% >>>
{%
MYifFloatTF{#1}
{MYifNumberTF{#2}}
{@secondoftwo}%
}% <<<
longdefMYifScientific@withe#1e#2endMYifScientific% >>>
{%
MYifFloatTF{#1}
{MYifNumberTF{#2}}
{@secondoftwo}%
}% <<<
MYif@groupify@TF{Scientific}
MYif@create@TandF@N@TandF{Scientific}
MYif@create@TandF@N@TandF{ScientificG}
% <<<
makeatother
usepackage{pgf}
begin{document}
deftestNum{3e+64}
MYifScientificNTF{testNum}
{%
pgfmathprintnumber[sci]{testNum} is a number
}
{%
pgfmathprintnumber[sci]{testNum} is not a number
}
end{document}
add a comment |
The following builds upon tests I've implemented elsewhere. I did not remove everything unnecessary for this answer to work, so it might add more stuff than necessary. The test for a group in the argument is from Check for group as argument (expandable).
The test should be fully expandable.
documentclass{article}
makeatletter
defendMYifargument{endMYifargument}
newcommandMYif@endMYifargument[1]% >>>
{%
ifxendMYifargument#1%
MYif@fiAa
else
MYif@fiBb
fi
}% <<<
% MYif@fi macros >>>
longdefMYif@fiAa#1fi#2#3{fi#2}
longdefMYif@fiAb#1fi#2#3{fi#3}
longdefMYif@fiBafi#1#2{fi#1}
longdefMYif@fiBbfi#1#2{fi#2}
longdefMYif@fiAy#1fi#2{fi#2}
longdefMYif@fiAn#1fi#2{fi}
longdefMYif@fiByfi#1{fi#1}
longdefMYif@fiBnfi#1{fi}
longdefMYif@fifiAa#1fifi#2#3{fi#2}
longdefMYif@fifiAb#1fifi#2#3{fi#3}
longdefMYif@fifiBAa#1fifi#2#3{fifi#2}
longdefMYif@fifiBAb#1fifi#2#3{fifi#3}
longdefMYif@fifiBBafifi#1#2{fifi#1}
longdefMYif@fifiBBbfifi#1#2{fifi#2}
% <<<
newcommand*MYif@groupify@TF[1]% >>>
{%
expandafterlongexpandafteredefcsname MYif#1GTFendcsname##1%
{%
unexpanded{MYifGroupTF}{##1}%
{unexpandedexpandafter{csname MYif#1GTFendcsname}##1}%
{unexpandedexpandafter{csname MYif#1TFendcsname}{##1}}%
}%
}% <<<
newcommand*MYif@create@TandF[1]% >>>
{%
expandafterlongexpandafteredefcsname MYif#1Tendcsname##1%
{%
unexpandedexpandafter{csname MYif#1TFendcsname}{##1}%
{noexpand@firstofone}
{noexpand@gobble}%
}%
expandafterlongexpandafteredefcsname MYif#1Fendcsname##1%
{%
unexpandedexpandafter{csname MYif#1TFendcsname}{##1}%
{noexpand@gobble}
{noexpand@firstofone}%
}%
}% <<<
newcommand*MYif@create@TandF@twoargs[1]% >>>
{%
expandafterlongexpandafteredefcsname MYif#1Tendcsname##1##2%
{%
unexpandedexpandafter{csname MYif#1TFendcsname}{##1}{##2}%
{noexpand@firstofone}
{noexpand@gobble}%
}%
expandafterlongexpandafteredefcsname MYif#1Fendcsname##1##2%
{%
unexpandedexpandafter{csname MYif#1TFendcsname}{##1}{##2}%
{noexpand@gobble}
{noexpand@firstofone}%
}%
}% <<<
newcommand*MYif@create@N@TandF[1]% >>>
{%
expandafterlongexpandafteredefcsname MYif#1NTFendcsname##1%
{%
noexpandexpandafter
expandafternoexpandcsname MYif#1TFendcsname
noexpandexpandafter{##1}%
}%
MYif@create@TandF{#1N}%
}% <<<
newcommand*MYif@create@N@TandF@twoargs[1]% >>>
{%
expandafterlongexpandafteredefcsname MYif#1NNTFendcsname##1##2%
{%
noexpandexpandafter
expandafternoexpandcsname MYif#1NNTF@aendcsname
noexpandexpandafter{##2}{##1}%
}%
expandafterlongexpandafteredefcsname MYif#1NNTF@aendcsname##1##2%
{%
noexpandexpandafter
expandafternoexpandcsname MYif#1TFendcsname
noexpandexpandafter{##2}{##1}%
}%
MYif@create@TandF@twoargs{#1NN}%
expandafterlongexpandafteredefcsname MYif#1NnTFendcsname##1##2%
{%
noexpandexpandafter
expandafternoexpandcsname MYif#1TFendcsname
noexpandexpandafter{##1}{##2}%
}%
MYif@create@TandF@twoargs{#1Nn}%
expandafterlongexpandafteredefcsname MYif#1nNTFendcsname##1##2%
{%
noexpandexpandafter
expandafternoexpandcsname MYif#1nNTF@aendcsname
noexpandexpandafter{##2}{##1}%
}%
expandafterlongexpandafteredefcsname MYif#1nNTF@aendcsname##1##2%
{%
expandafternoexpandcsname MYif#1TFendcsname{##2}{##1}
}%
MYif@create@TandF@twoargs{#1nN}%
}% <<<
newcommand*MYif@create@TandF@N@TandF[1]% >>>
{%
MYif@create@TandF{#1}%
MYif@create@N@TandF{#1}%
}% <<<
newcommand*MYif@create@TandF@N@TandF@twoargs[1]% >>>
{%
MYif@create@TandF@twoargs{#1}%
MYif@create@N@TandF@twoargs{#1}%
}% <<<
newcommandMYif@notEmpty@noGroup@noSpace[2]% >>>
{%
MYifEmptyTF{#1}
{@secondoftwo}
{%
MYifContainsGroupTF{#1}
{@secondoftwo}
{%
MYifContainsSpaceTF{#1}
{@secondoftwo}
{#2}%
}%
}%
}% <<<
% MYifEmpty >>>
newcommandMYifEmptyTF[1]% >>>
{%
ifrelaxdetokenize{#1}relax
MYif@fiAa
else
MYif@fiBb
fi
}% <<<
newcommandMYifEmptyT[1]{% >>>
ifrelaxdetokenize{#1}relax
MYif@fiAy
else
MYif@fiBn
fi}
% <<<
newcommandMYifEmptyF[1]{% >>>
ifrelaxdetokenize{#1}relax
MYif@fiAn
else
MYif@fiBy
fi}
% <<<
newcommandMYifEmptyNTF[1]% >>>
{expandafterMYifEmptyTFexpandafter{#1}}% <<<
newcommandMYifEmptyNT[1]% >>>
{expandafterMYifEmptyTexpandafter{#1}}% <<<
newcommandMYifEmptyNF[1]% >>>
{expandafterMYifEmptyFexpandafter{#1}}% <<<
MYif@groupify@TF{Empty}
MYif@create@TandF@N@TandF{EmptyG}
% <<<
% MYifContainsGroup >>>
newcommandMYifContainsGroupTF[1]% >>>
{%
expandafterMYifContainsGroup@a
MYifContainsGroup@eat#1{}%
MYifContainsGroup@endargument
}% <<<
longdefMYifContainsGroup@eat#1#{}
longdefMYifContainsGroup@a#1MYifContainsGroup@endargument% >>>
{%
MYifEmptyTF{#1}
{@secondoftwo}
{@firstoftwo}%
}% <<<
MYif@groupify@TF{ContainsGroup}
MYif@create@TandF@N@TandF{ContainsGroup}
MYif@create@TandF@N@TandF{ContainsGroupG}
% <<<
% MYifContainsSpace >>>
newcommandMYifContainsSpaceTF[1]% >>>
{%
expandafterMYifContainsSpace@a
MYifContainsSpace@eat#1
MYifContainsSpace@endargument
}% <<<
longdefMYifContainsSpace@a#1MYifContainsSpace@endargument% >>>
{%
MYifEmptyTF{#1}
{@secondoftwo}
{@firstoftwo}%
}% <<<
longdefMYifContainsSpace@eat#1 {}
MYif@groupify@TF{ContainsSpace}
MYif@create@TandF@N@TandF{ContainsSpace}
MYif@create@TandF@N@TandF{ContainsSpaceG}
% <<<
% MYifDigit >>>
newcommandMYifDigitTF[1]% >>>
{%
MYifOneTokenNoGroupTF{#1}
{MYifDigit@a{#1}}
{@secondoftwo}%
}% <<<
newcommandMYifDigit@a[1]% >>>
{%
ifx0#1MYif@fiAa
elseMYifDigit@b1#1%
elseMYifDigit@b2#1%
elseMYifDigit@b3#1%
elseMYifDigit@b4#1%
elseMYifDigit@b5#1%
elseMYifDigit@b6#1%
elseMYifDigit@b7#1%
elseMYifDigit@b8#1%
elseMYifDigit@b9#1%
elseMYif@fiBb
fi
}% <<<
newcommandMYifDigit@b[2]% >>>
{%
fiifx#1#2MYif@fiAa
}% <<<
newcommandMYifDigitGTF[1]% >>>
{%
MYifGroupTF{#1}
{MYifDigitGTF#1}
{%
MYifOneTokenTF{#1}
{MYifDigit@a{#1}}
{@secondoftwo}%
}%
}% <<<
MYif@create@TandF@N@TandF{Digit}
MYif@create@TandF@N@TandF{DigitG}
% <<<
% MYifNumber >>>
newcommandMYifNumberTF[1]% >>>
{%
MYif@notEmpty@noGroup@noSpace{#1}{MYifNumber@ifSign#1endMYifargument}%
}% <<<
newcommandMYifNumber@ifSign[1]% >>>
{%
ifx+#1%
MYif@fifiAa
else
ifx-#1%
MYif@fifiBAa
else
MYif@fifiBBb
fi
fi
{MYifNumber@ifDigit@noend}
{MYifNumber@ifDigit#1}
}% <<<
newcommandMYifNumber@ifDigit[1]% >>>
{%
MYif@endMYifargument{#1}
{@firstoftwo}
{%
MYifDigit@a{#1}
{MYifNumber@ifDigit}
{MYifNumber@false}%
}%
}% <<<
newcommandMYifNumber@ifDigit@noend[1]% >>>
{%
MYif@endMYifargument{#1}
{@secondoftwo}
{%
MYifDigit@a{#1}
{MYifNumber@ifDigit}
{MYifNumber@false}%
}%
}% <<<
longdefMYifNumber@false#1endMYifargument% >>>
{%
@secondoftwo
}% <<<
MYif@groupify@TF{Number}
MYif@create@TandF@N@TandF{Number}
MYif@create@TandF@N@TandF{NumberG}
% <<<
% MYifFloat >>>
newcommandMYifFloatTF[1]% >>>
{%
MYif@notEmpty@noGroup@noSpace{#1}{MYifFloat@a{#1}}
}% <<<
%newcommandMYifFloat@a newcommandMYifFloat@ifDot >>>
begingroup
catcode`?=4
defMYif@zz
{%
endgroup
newcommandMYifFloat@a[1]% >>>
{%
MYifFloat@ifDot{##1}
{MYifFloat@withDot##1MYifFloat@endargument}
{MYifNumber@ifSign##1endMYifargument}%
}% <<<
newcommandMYifFloat@ifDot[1]% >>>
{%
MYifFloat@ifDot@a##1.?MYifFloat@endargument
}% <<<
longdefMYifFloat@ifDot@a##1.##2MYifFloat@endargument% >>>
{%
ifx?##2%
MYif@fiAb
else
MYif@fiBa
fi
}% <<<
}
MYif@zz
% <<<
longdefMYifFloat@withDot#1.#2MYifFloat@endargument% >>>
{%
MYifEmptyTF{#1}
{MYifNumber@ifDigit@noend#2endMYifargument}
{%
MYifNumber@ifSign#1endMYifargument
{MYifNumber@ifDigit#2endMYifargument}
{@secondoftwo}%
}%
}% <<<
MYif@groupify@TF{Float}
MYif@create@TandF@N@TandF{Float}
MYif@create@TandF@N@TandF{FloatG}
% <<<
% MYifContainsE >>>
newcommandMYifContainseTF[1]% >>>
{%
MYifContainsE@e#1eMYifContainsE@end
{@secondoftwo}
{@firstoftwo}%
}% <<<
longdefMYifContainsE@e#1e#2MYifContainsE@end% >>>
{%
MYifEmptyTF{#2}%
}% <<<
newcommandMYifContainsETF[1]% >>>
{%
MYifContainsE@E#1EMYifContainsE@end
{@secondoftwo}
{@firstoftwo}%
}% <<<
longdefMYifContainsE@E#1E#2MYifContainsE@end% >>>
{%
MYifEmptyTF{#2}%
}% <<<
% <<<
% MYifScientific >>>
newcommandMYifScientificTF[1]% >>>
{%
MYifContainsETF{#1}
{MYifScientific@withE#1endMYifScientific}
{%
MYifContainseTF{#1}
{MYifScientific@withe#1endMYifScientific}
{MYifFloatTF{#1}}%
}%
}% <<<
longdefMYifScientific@withE#1E#2endMYifScientific% >>>
{%
MYifFloatTF{#1}
{MYifNumberTF{#2}}
{@secondoftwo}%
}% <<<
longdefMYifScientific@withe#1e#2endMYifScientific% >>>
{%
MYifFloatTF{#1}
{MYifNumberTF{#2}}
{@secondoftwo}%
}% <<<
MYif@groupify@TF{Scientific}
MYif@create@TandF@N@TandF{Scientific}
MYif@create@TandF@N@TandF{ScientificG}
% <<<
makeatother
usepackage{pgf}
begin{document}
deftestNum{3e+64}
MYifScientificNTF{testNum}
{%
pgfmathprintnumber[sci]{testNum} is a number
}
{%
pgfmathprintnumber[sci]{testNum} is not a number
}
end{document}
add a comment |
The following builds upon tests I've implemented elsewhere. I did not remove everything unnecessary for this answer to work, so it might add more stuff than necessary. The test for a group in the argument is from Check for group as argument (expandable).
The test should be fully expandable.
documentclass{article}
makeatletter
defendMYifargument{endMYifargument}
newcommandMYif@endMYifargument[1]% >>>
{%
ifxendMYifargument#1%
MYif@fiAa
else
MYif@fiBb
fi
}% <<<
% MYif@fi macros >>>
longdefMYif@fiAa#1fi#2#3{fi#2}
longdefMYif@fiAb#1fi#2#3{fi#3}
longdefMYif@fiBafi#1#2{fi#1}
longdefMYif@fiBbfi#1#2{fi#2}
longdefMYif@fiAy#1fi#2{fi#2}
longdefMYif@fiAn#1fi#2{fi}
longdefMYif@fiByfi#1{fi#1}
longdefMYif@fiBnfi#1{fi}
longdefMYif@fifiAa#1fifi#2#3{fi#2}
longdefMYif@fifiAb#1fifi#2#3{fi#3}
longdefMYif@fifiBAa#1fifi#2#3{fifi#2}
longdefMYif@fifiBAb#1fifi#2#3{fifi#3}
longdefMYif@fifiBBafifi#1#2{fifi#1}
longdefMYif@fifiBBbfifi#1#2{fifi#2}
% <<<
newcommand*MYif@groupify@TF[1]% >>>
{%
expandafterlongexpandafteredefcsname MYif#1GTFendcsname##1%
{%
unexpanded{MYifGroupTF}{##1}%
{unexpandedexpandafter{csname MYif#1GTFendcsname}##1}%
{unexpandedexpandafter{csname MYif#1TFendcsname}{##1}}%
}%
}% <<<
newcommand*MYif@create@TandF[1]% >>>
{%
expandafterlongexpandafteredefcsname MYif#1Tendcsname##1%
{%
unexpandedexpandafter{csname MYif#1TFendcsname}{##1}%
{noexpand@firstofone}
{noexpand@gobble}%
}%
expandafterlongexpandafteredefcsname MYif#1Fendcsname##1%
{%
unexpandedexpandafter{csname MYif#1TFendcsname}{##1}%
{noexpand@gobble}
{noexpand@firstofone}%
}%
}% <<<
newcommand*MYif@create@TandF@twoargs[1]% >>>
{%
expandafterlongexpandafteredefcsname MYif#1Tendcsname##1##2%
{%
unexpandedexpandafter{csname MYif#1TFendcsname}{##1}{##2}%
{noexpand@firstofone}
{noexpand@gobble}%
}%
expandafterlongexpandafteredefcsname MYif#1Fendcsname##1##2%
{%
unexpandedexpandafter{csname MYif#1TFendcsname}{##1}{##2}%
{noexpand@gobble}
{noexpand@firstofone}%
}%
}% <<<
newcommand*MYif@create@N@TandF[1]% >>>
{%
expandafterlongexpandafteredefcsname MYif#1NTFendcsname##1%
{%
noexpandexpandafter
expandafternoexpandcsname MYif#1TFendcsname
noexpandexpandafter{##1}%
}%
MYif@create@TandF{#1N}%
}% <<<
newcommand*MYif@create@N@TandF@twoargs[1]% >>>
{%
expandafterlongexpandafteredefcsname MYif#1NNTFendcsname##1##2%
{%
noexpandexpandafter
expandafternoexpandcsname MYif#1NNTF@aendcsname
noexpandexpandafter{##2}{##1}%
}%
expandafterlongexpandafteredefcsname MYif#1NNTF@aendcsname##1##2%
{%
noexpandexpandafter
expandafternoexpandcsname MYif#1TFendcsname
noexpandexpandafter{##2}{##1}%
}%
MYif@create@TandF@twoargs{#1NN}%
expandafterlongexpandafteredefcsname MYif#1NnTFendcsname##1##2%
{%
noexpandexpandafter
expandafternoexpandcsname MYif#1TFendcsname
noexpandexpandafter{##1}{##2}%
}%
MYif@create@TandF@twoargs{#1Nn}%
expandafterlongexpandafteredefcsname MYif#1nNTFendcsname##1##2%
{%
noexpandexpandafter
expandafternoexpandcsname MYif#1nNTF@aendcsname
noexpandexpandafter{##2}{##1}%
}%
expandafterlongexpandafteredefcsname MYif#1nNTF@aendcsname##1##2%
{%
expandafternoexpandcsname MYif#1TFendcsname{##2}{##1}
}%
MYif@create@TandF@twoargs{#1nN}%
}% <<<
newcommand*MYif@create@TandF@N@TandF[1]% >>>
{%
MYif@create@TandF{#1}%
MYif@create@N@TandF{#1}%
}% <<<
newcommand*MYif@create@TandF@N@TandF@twoargs[1]% >>>
{%
MYif@create@TandF@twoargs{#1}%
MYif@create@N@TandF@twoargs{#1}%
}% <<<
newcommandMYif@notEmpty@noGroup@noSpace[2]% >>>
{%
MYifEmptyTF{#1}
{@secondoftwo}
{%
MYifContainsGroupTF{#1}
{@secondoftwo}
{%
MYifContainsSpaceTF{#1}
{@secondoftwo}
{#2}%
}%
}%
}% <<<
% MYifEmpty >>>
newcommandMYifEmptyTF[1]% >>>
{%
ifrelaxdetokenize{#1}relax
MYif@fiAa
else
MYif@fiBb
fi
}% <<<
newcommandMYifEmptyT[1]{% >>>
ifrelaxdetokenize{#1}relax
MYif@fiAy
else
MYif@fiBn
fi}
% <<<
newcommandMYifEmptyF[1]{% >>>
ifrelaxdetokenize{#1}relax
MYif@fiAn
else
MYif@fiBy
fi}
% <<<
newcommandMYifEmptyNTF[1]% >>>
{expandafterMYifEmptyTFexpandafter{#1}}% <<<
newcommandMYifEmptyNT[1]% >>>
{expandafterMYifEmptyTexpandafter{#1}}% <<<
newcommandMYifEmptyNF[1]% >>>
{expandafterMYifEmptyFexpandafter{#1}}% <<<
MYif@groupify@TF{Empty}
MYif@create@TandF@N@TandF{EmptyG}
% <<<
% MYifContainsGroup >>>
newcommandMYifContainsGroupTF[1]% >>>
{%
expandafterMYifContainsGroup@a
MYifContainsGroup@eat#1{}%
MYifContainsGroup@endargument
}% <<<
longdefMYifContainsGroup@eat#1#{}
longdefMYifContainsGroup@a#1MYifContainsGroup@endargument% >>>
{%
MYifEmptyTF{#1}
{@secondoftwo}
{@firstoftwo}%
}% <<<
MYif@groupify@TF{ContainsGroup}
MYif@create@TandF@N@TandF{ContainsGroup}
MYif@create@TandF@N@TandF{ContainsGroupG}
% <<<
% MYifContainsSpace >>>
newcommandMYifContainsSpaceTF[1]% >>>
{%
expandafterMYifContainsSpace@a
MYifContainsSpace@eat#1
MYifContainsSpace@endargument
}% <<<
longdefMYifContainsSpace@a#1MYifContainsSpace@endargument% >>>
{%
MYifEmptyTF{#1}
{@secondoftwo}
{@firstoftwo}%
}% <<<
longdefMYifContainsSpace@eat#1 {}
MYif@groupify@TF{ContainsSpace}
MYif@create@TandF@N@TandF{ContainsSpace}
MYif@create@TandF@N@TandF{ContainsSpaceG}
% <<<
% MYifDigit >>>
newcommandMYifDigitTF[1]% >>>
{%
MYifOneTokenNoGroupTF{#1}
{MYifDigit@a{#1}}
{@secondoftwo}%
}% <<<
newcommandMYifDigit@a[1]% >>>
{%
ifx0#1MYif@fiAa
elseMYifDigit@b1#1%
elseMYifDigit@b2#1%
elseMYifDigit@b3#1%
elseMYifDigit@b4#1%
elseMYifDigit@b5#1%
elseMYifDigit@b6#1%
elseMYifDigit@b7#1%
elseMYifDigit@b8#1%
elseMYifDigit@b9#1%
elseMYif@fiBb
fi
}% <<<
newcommandMYifDigit@b[2]% >>>
{%
fiifx#1#2MYif@fiAa
}% <<<
newcommandMYifDigitGTF[1]% >>>
{%
MYifGroupTF{#1}
{MYifDigitGTF#1}
{%
MYifOneTokenTF{#1}
{MYifDigit@a{#1}}
{@secondoftwo}%
}%
}% <<<
MYif@create@TandF@N@TandF{Digit}
MYif@create@TandF@N@TandF{DigitG}
% <<<
% MYifNumber >>>
newcommandMYifNumberTF[1]% >>>
{%
MYif@notEmpty@noGroup@noSpace{#1}{MYifNumber@ifSign#1endMYifargument}%
}% <<<
newcommandMYifNumber@ifSign[1]% >>>
{%
ifx+#1%
MYif@fifiAa
else
ifx-#1%
MYif@fifiBAa
else
MYif@fifiBBb
fi
fi
{MYifNumber@ifDigit@noend}
{MYifNumber@ifDigit#1}
}% <<<
newcommandMYifNumber@ifDigit[1]% >>>
{%
MYif@endMYifargument{#1}
{@firstoftwo}
{%
MYifDigit@a{#1}
{MYifNumber@ifDigit}
{MYifNumber@false}%
}%
}% <<<
newcommandMYifNumber@ifDigit@noend[1]% >>>
{%
MYif@endMYifargument{#1}
{@secondoftwo}
{%
MYifDigit@a{#1}
{MYifNumber@ifDigit}
{MYifNumber@false}%
}%
}% <<<
longdefMYifNumber@false#1endMYifargument% >>>
{%
@secondoftwo
}% <<<
MYif@groupify@TF{Number}
MYif@create@TandF@N@TandF{Number}
MYif@create@TandF@N@TandF{NumberG}
% <<<
% MYifFloat >>>
newcommandMYifFloatTF[1]% >>>
{%
MYif@notEmpty@noGroup@noSpace{#1}{MYifFloat@a{#1}}
}% <<<
%newcommandMYifFloat@a newcommandMYifFloat@ifDot >>>
begingroup
catcode`?=4
defMYif@zz
{%
endgroup
newcommandMYifFloat@a[1]% >>>
{%
MYifFloat@ifDot{##1}
{MYifFloat@withDot##1MYifFloat@endargument}
{MYifNumber@ifSign##1endMYifargument}%
}% <<<
newcommandMYifFloat@ifDot[1]% >>>
{%
MYifFloat@ifDot@a##1.?MYifFloat@endargument
}% <<<
longdefMYifFloat@ifDot@a##1.##2MYifFloat@endargument% >>>
{%
ifx?##2%
MYif@fiAb
else
MYif@fiBa
fi
}% <<<
}
MYif@zz
% <<<
longdefMYifFloat@withDot#1.#2MYifFloat@endargument% >>>
{%
MYifEmptyTF{#1}
{MYifNumber@ifDigit@noend#2endMYifargument}
{%
MYifNumber@ifSign#1endMYifargument
{MYifNumber@ifDigit#2endMYifargument}
{@secondoftwo}%
}%
}% <<<
MYif@groupify@TF{Float}
MYif@create@TandF@N@TandF{Float}
MYif@create@TandF@N@TandF{FloatG}
% <<<
% MYifContainsE >>>
newcommandMYifContainseTF[1]% >>>
{%
MYifContainsE@e#1eMYifContainsE@end
{@secondoftwo}
{@firstoftwo}%
}% <<<
longdefMYifContainsE@e#1e#2MYifContainsE@end% >>>
{%
MYifEmptyTF{#2}%
}% <<<
newcommandMYifContainsETF[1]% >>>
{%
MYifContainsE@E#1EMYifContainsE@end
{@secondoftwo}
{@firstoftwo}%
}% <<<
longdefMYifContainsE@E#1E#2MYifContainsE@end% >>>
{%
MYifEmptyTF{#2}%
}% <<<
% <<<
% MYifScientific >>>
newcommandMYifScientificTF[1]% >>>
{%
MYifContainsETF{#1}
{MYifScientific@withE#1endMYifScientific}
{%
MYifContainseTF{#1}
{MYifScientific@withe#1endMYifScientific}
{MYifFloatTF{#1}}%
}%
}% <<<
longdefMYifScientific@withE#1E#2endMYifScientific% >>>
{%
MYifFloatTF{#1}
{MYifNumberTF{#2}}
{@secondoftwo}%
}% <<<
longdefMYifScientific@withe#1e#2endMYifScientific% >>>
{%
MYifFloatTF{#1}
{MYifNumberTF{#2}}
{@secondoftwo}%
}% <<<
MYif@groupify@TF{Scientific}
MYif@create@TandF@N@TandF{Scientific}
MYif@create@TandF@N@TandF{ScientificG}
% <<<
makeatother
usepackage{pgf}
begin{document}
deftestNum{3e+64}
MYifScientificNTF{testNum}
{%
pgfmathprintnumber[sci]{testNum} is a number
}
{%
pgfmathprintnumber[sci]{testNum} is not a number
}
end{document}
The following builds upon tests I've implemented elsewhere. I did not remove everything unnecessary for this answer to work, so it might add more stuff than necessary. The test for a group in the argument is from Check for group as argument (expandable).
The test should be fully expandable.
documentclass{article}
makeatletter
defendMYifargument{endMYifargument}
newcommandMYif@endMYifargument[1]% >>>
{%
ifxendMYifargument#1%
MYif@fiAa
else
MYif@fiBb
fi
}% <<<
% MYif@fi macros >>>
longdefMYif@fiAa#1fi#2#3{fi#2}
longdefMYif@fiAb#1fi#2#3{fi#3}
longdefMYif@fiBafi#1#2{fi#1}
longdefMYif@fiBbfi#1#2{fi#2}
longdefMYif@fiAy#1fi#2{fi#2}
longdefMYif@fiAn#1fi#2{fi}
longdefMYif@fiByfi#1{fi#1}
longdefMYif@fiBnfi#1{fi}
longdefMYif@fifiAa#1fifi#2#3{fi#2}
longdefMYif@fifiAb#1fifi#2#3{fi#3}
longdefMYif@fifiBAa#1fifi#2#3{fifi#2}
longdefMYif@fifiBAb#1fifi#2#3{fifi#3}
longdefMYif@fifiBBafifi#1#2{fifi#1}
longdefMYif@fifiBBbfifi#1#2{fifi#2}
% <<<
newcommand*MYif@groupify@TF[1]% >>>
{%
expandafterlongexpandafteredefcsname MYif#1GTFendcsname##1%
{%
unexpanded{MYifGroupTF}{##1}%
{unexpandedexpandafter{csname MYif#1GTFendcsname}##1}%
{unexpandedexpandafter{csname MYif#1TFendcsname}{##1}}%
}%
}% <<<
newcommand*MYif@create@TandF[1]% >>>
{%
expandafterlongexpandafteredefcsname MYif#1Tendcsname##1%
{%
unexpandedexpandafter{csname MYif#1TFendcsname}{##1}%
{noexpand@firstofone}
{noexpand@gobble}%
}%
expandafterlongexpandafteredefcsname MYif#1Fendcsname##1%
{%
unexpandedexpandafter{csname MYif#1TFendcsname}{##1}%
{noexpand@gobble}
{noexpand@firstofone}%
}%
}% <<<
newcommand*MYif@create@TandF@twoargs[1]% >>>
{%
expandafterlongexpandafteredefcsname MYif#1Tendcsname##1##2%
{%
unexpandedexpandafter{csname MYif#1TFendcsname}{##1}{##2}%
{noexpand@firstofone}
{noexpand@gobble}%
}%
expandafterlongexpandafteredefcsname MYif#1Fendcsname##1##2%
{%
unexpandedexpandafter{csname MYif#1TFendcsname}{##1}{##2}%
{noexpand@gobble}
{noexpand@firstofone}%
}%
}% <<<
newcommand*MYif@create@N@TandF[1]% >>>
{%
expandafterlongexpandafteredefcsname MYif#1NTFendcsname##1%
{%
noexpandexpandafter
expandafternoexpandcsname MYif#1TFendcsname
noexpandexpandafter{##1}%
}%
MYif@create@TandF{#1N}%
}% <<<
newcommand*MYif@create@N@TandF@twoargs[1]% >>>
{%
expandafterlongexpandafteredefcsname MYif#1NNTFendcsname##1##2%
{%
noexpandexpandafter
expandafternoexpandcsname MYif#1NNTF@aendcsname
noexpandexpandafter{##2}{##1}%
}%
expandafterlongexpandafteredefcsname MYif#1NNTF@aendcsname##1##2%
{%
noexpandexpandafter
expandafternoexpandcsname MYif#1TFendcsname
noexpandexpandafter{##2}{##1}%
}%
MYif@create@TandF@twoargs{#1NN}%
expandafterlongexpandafteredefcsname MYif#1NnTFendcsname##1##2%
{%
noexpandexpandafter
expandafternoexpandcsname MYif#1TFendcsname
noexpandexpandafter{##1}{##2}%
}%
MYif@create@TandF@twoargs{#1Nn}%
expandafterlongexpandafteredefcsname MYif#1nNTFendcsname##1##2%
{%
noexpandexpandafter
expandafternoexpandcsname MYif#1nNTF@aendcsname
noexpandexpandafter{##2}{##1}%
}%
expandafterlongexpandafteredefcsname MYif#1nNTF@aendcsname##1##2%
{%
expandafternoexpandcsname MYif#1TFendcsname{##2}{##1}
}%
MYif@create@TandF@twoargs{#1nN}%
}% <<<
newcommand*MYif@create@TandF@N@TandF[1]% >>>
{%
MYif@create@TandF{#1}%
MYif@create@N@TandF{#1}%
}% <<<
newcommand*MYif@create@TandF@N@TandF@twoargs[1]% >>>
{%
MYif@create@TandF@twoargs{#1}%
MYif@create@N@TandF@twoargs{#1}%
}% <<<
newcommandMYif@notEmpty@noGroup@noSpace[2]% >>>
{%
MYifEmptyTF{#1}
{@secondoftwo}
{%
MYifContainsGroupTF{#1}
{@secondoftwo}
{%
MYifContainsSpaceTF{#1}
{@secondoftwo}
{#2}%
}%
}%
}% <<<
% MYifEmpty >>>
newcommandMYifEmptyTF[1]% >>>
{%
ifrelaxdetokenize{#1}relax
MYif@fiAa
else
MYif@fiBb
fi
}% <<<
newcommandMYifEmptyT[1]{% >>>
ifrelaxdetokenize{#1}relax
MYif@fiAy
else
MYif@fiBn
fi}
% <<<
newcommandMYifEmptyF[1]{% >>>
ifrelaxdetokenize{#1}relax
MYif@fiAn
else
MYif@fiBy
fi}
% <<<
newcommandMYifEmptyNTF[1]% >>>
{expandafterMYifEmptyTFexpandafter{#1}}% <<<
newcommandMYifEmptyNT[1]% >>>
{expandafterMYifEmptyTexpandafter{#1}}% <<<
newcommandMYifEmptyNF[1]% >>>
{expandafterMYifEmptyFexpandafter{#1}}% <<<
MYif@groupify@TF{Empty}
MYif@create@TandF@N@TandF{EmptyG}
% <<<
% MYifContainsGroup >>>
newcommandMYifContainsGroupTF[1]% >>>
{%
expandafterMYifContainsGroup@a
MYifContainsGroup@eat#1{}%
MYifContainsGroup@endargument
}% <<<
longdefMYifContainsGroup@eat#1#{}
longdefMYifContainsGroup@a#1MYifContainsGroup@endargument% >>>
{%
MYifEmptyTF{#1}
{@secondoftwo}
{@firstoftwo}%
}% <<<
MYif@groupify@TF{ContainsGroup}
MYif@create@TandF@N@TandF{ContainsGroup}
MYif@create@TandF@N@TandF{ContainsGroupG}
% <<<
% MYifContainsSpace >>>
newcommandMYifContainsSpaceTF[1]% >>>
{%
expandafterMYifContainsSpace@a
MYifContainsSpace@eat#1
MYifContainsSpace@endargument
}% <<<
longdefMYifContainsSpace@a#1MYifContainsSpace@endargument% >>>
{%
MYifEmptyTF{#1}
{@secondoftwo}
{@firstoftwo}%
}% <<<
longdefMYifContainsSpace@eat#1 {}
MYif@groupify@TF{ContainsSpace}
MYif@create@TandF@N@TandF{ContainsSpace}
MYif@create@TandF@N@TandF{ContainsSpaceG}
% <<<
% MYifDigit >>>
newcommandMYifDigitTF[1]% >>>
{%
MYifOneTokenNoGroupTF{#1}
{MYifDigit@a{#1}}
{@secondoftwo}%
}% <<<
newcommandMYifDigit@a[1]% >>>
{%
ifx0#1MYif@fiAa
elseMYifDigit@b1#1%
elseMYifDigit@b2#1%
elseMYifDigit@b3#1%
elseMYifDigit@b4#1%
elseMYifDigit@b5#1%
elseMYifDigit@b6#1%
elseMYifDigit@b7#1%
elseMYifDigit@b8#1%
elseMYifDigit@b9#1%
elseMYif@fiBb
fi
}% <<<
newcommandMYifDigit@b[2]% >>>
{%
fiifx#1#2MYif@fiAa
}% <<<
newcommandMYifDigitGTF[1]% >>>
{%
MYifGroupTF{#1}
{MYifDigitGTF#1}
{%
MYifOneTokenTF{#1}
{MYifDigit@a{#1}}
{@secondoftwo}%
}%
}% <<<
MYif@create@TandF@N@TandF{Digit}
MYif@create@TandF@N@TandF{DigitG}
% <<<
% MYifNumber >>>
newcommandMYifNumberTF[1]% >>>
{%
MYif@notEmpty@noGroup@noSpace{#1}{MYifNumber@ifSign#1endMYifargument}%
}% <<<
newcommandMYifNumber@ifSign[1]% >>>
{%
ifx+#1%
MYif@fifiAa
else
ifx-#1%
MYif@fifiBAa
else
MYif@fifiBBb
fi
fi
{MYifNumber@ifDigit@noend}
{MYifNumber@ifDigit#1}
}% <<<
newcommandMYifNumber@ifDigit[1]% >>>
{%
MYif@endMYifargument{#1}
{@firstoftwo}
{%
MYifDigit@a{#1}
{MYifNumber@ifDigit}
{MYifNumber@false}%
}%
}% <<<
newcommandMYifNumber@ifDigit@noend[1]% >>>
{%
MYif@endMYifargument{#1}
{@secondoftwo}
{%
MYifDigit@a{#1}
{MYifNumber@ifDigit}
{MYifNumber@false}%
}%
}% <<<
longdefMYifNumber@false#1endMYifargument% >>>
{%
@secondoftwo
}% <<<
MYif@groupify@TF{Number}
MYif@create@TandF@N@TandF{Number}
MYif@create@TandF@N@TandF{NumberG}
% <<<
% MYifFloat >>>
newcommandMYifFloatTF[1]% >>>
{%
MYif@notEmpty@noGroup@noSpace{#1}{MYifFloat@a{#1}}
}% <<<
%newcommandMYifFloat@a newcommandMYifFloat@ifDot >>>
begingroup
catcode`?=4
defMYif@zz
{%
endgroup
newcommandMYifFloat@a[1]% >>>
{%
MYifFloat@ifDot{##1}
{MYifFloat@withDot##1MYifFloat@endargument}
{MYifNumber@ifSign##1endMYifargument}%
}% <<<
newcommandMYifFloat@ifDot[1]% >>>
{%
MYifFloat@ifDot@a##1.?MYifFloat@endargument
}% <<<
longdefMYifFloat@ifDot@a##1.##2MYifFloat@endargument% >>>
{%
ifx?##2%
MYif@fiAb
else
MYif@fiBa
fi
}% <<<
}
MYif@zz
% <<<
longdefMYifFloat@withDot#1.#2MYifFloat@endargument% >>>
{%
MYifEmptyTF{#1}
{MYifNumber@ifDigit@noend#2endMYifargument}
{%
MYifNumber@ifSign#1endMYifargument
{MYifNumber@ifDigit#2endMYifargument}
{@secondoftwo}%
}%
}% <<<
MYif@groupify@TF{Float}
MYif@create@TandF@N@TandF{Float}
MYif@create@TandF@N@TandF{FloatG}
% <<<
% MYifContainsE >>>
newcommandMYifContainseTF[1]% >>>
{%
MYifContainsE@e#1eMYifContainsE@end
{@secondoftwo}
{@firstoftwo}%
}% <<<
longdefMYifContainsE@e#1e#2MYifContainsE@end% >>>
{%
MYifEmptyTF{#2}%
}% <<<
newcommandMYifContainsETF[1]% >>>
{%
MYifContainsE@E#1EMYifContainsE@end
{@secondoftwo}
{@firstoftwo}%
}% <<<
longdefMYifContainsE@E#1E#2MYifContainsE@end% >>>
{%
MYifEmptyTF{#2}%
}% <<<
% <<<
% MYifScientific >>>
newcommandMYifScientificTF[1]% >>>
{%
MYifContainsETF{#1}
{MYifScientific@withE#1endMYifScientific}
{%
MYifContainseTF{#1}
{MYifScientific@withe#1endMYifScientific}
{MYifFloatTF{#1}}%
}%
}% <<<
longdefMYifScientific@withE#1E#2endMYifScientific% >>>
{%
MYifFloatTF{#1}
{MYifNumberTF{#2}}
{@secondoftwo}%
}% <<<
longdefMYifScientific@withe#1e#2endMYifScientific% >>>
{%
MYifFloatTF{#1}
{MYifNumberTF{#2}}
{@secondoftwo}%
}% <<<
MYif@groupify@TF{Scientific}
MYif@create@TandF@N@TandF{Scientific}
MYif@create@TandF@N@TandF{ScientificG}
% <<<
makeatother
usepackage{pgf}
begin{document}
deftestNum{3e+64}
MYifScientificNTF{testNum}
{%
pgfmathprintnumber[sci]{testNum} is a number
}
{%
pgfmathprintnumber[sci]{testNum} is not a number
}
end{document}
edited Dec 8 at 14:47
answered Dec 8 at 14:31
Skillmon
21k11941
21k11941
add a comment |
add a comment |
Thanks for contributing an answer to TeX - LaTeX Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f463814%2fcheck-whether-string-represents-valid-number-for-pgf%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown