1

I am using this code to get a better control when scientific notation should be used and when not.

The problem is, that it doesn't seem not to be compatible when using comma as decimal separator, for example:

% 
\documentclass[a4paper,12pt]{article}

\usepackage[locale=DE,per-mode=fraction,round-pad=false]{siunitx}

\usepackage[low=1e-2,high=1e3]{threshold}

\begin{document}

\SI{5.2}{m} works but %\SI{5,2}{m} not. \end{document}

% threshold.sty
\RequirePackage{expl3,kvoptions,siunitx}
\SetupKeyvalOptions{family=threshold,prefix=threshold@}
\DeclareStringOption[1]{low}[0.001]
\DeclareStringOption[1]{high}[100]
\ProcessKeyvalOptions*
\sisetup{scientific-notation=true}
\ExplSyntaxOn
    \cs_new_eq:NN \fpcmpTF \fp_compare:nTF
\ExplSyntaxOff
\let\OldNum\num%
\renewcommand*{\num}[2][]{%
    \fpcmpTF{abs(#2)<=\threshold@low}{%
        \OldNum[scientific-notation=true,#1]{#2}%
    }{%
        \fpcmpTF{abs(#2)>=\threshold@high}{%
            \OldNum[scientific-notation=true,#1]{#2}%
        }{%
            \OldNum[scientific-notation=false,#1]{#2}%
        }%
    }%
}

\let\OldSI\SI%
\renewcommand*{\SI}[3][]{%
    \fpcmpTF{abs(#2)<=\threshold@low}{%
        \OldSI[scientific-notation=true,#1]{#2}{#3}%
    }{%
        \fpcmpTF{abs(#2)>=\threshold@high}{%
            \OldSI[scientific-notation=true,#1]{#2}{#3}%
        }{%
            \OldSI[scientific-notation=false,#1]{#2}{#3}%
        }%
    }%
}

How can I make it work with comma separator as well.

Julia
  • 1,648
  • In fp, if abs(#2) is fed a number with commas instead of decimal points, it will probably fail. You probably need something like abs(\num[output-decinal-marker=., ]{#2}) or something in that line... (no time to check now) – Rmano Aug 29 '22 at 13:24
  • 1
    @Rmano doubt that this will work, \num isn't expandable, will not work in abs() :) What could work would be: \RequirePackage{etl}, then after your \ExplSyntaxOn put \etl_new_replace_once:Nn \thresholdcomma { , }, then in abs(#2) use abs(\thresholdcomma{#2}{.}) instead. – Skillmon Aug 29 '22 at 13:29
  • 1
    Yes --- right you are. And @Julia: I suggest NOT to overload \num --- nor any basic command. Use your own macro... – Rmano Aug 29 '22 at 13:31
  • @Rmano especially since the way \num and \SI are copied here only works because siunitx uses \NewDocumentCommand and not \newcommand. – Skillmon Aug 29 '22 at 13:40
  • 1
    @Julia you should use \NewCommandCopy instead of \let for this. – Skillmon Aug 29 '22 at 13:41
  • @Skillmon: Thanks it works! Maybe you can convert the comment to an answer such that I can accept it. I further noticed that \SI{e-2}{m} (instead of \SI{1e-2}{m}) raises a similar error. Do you have also an idea about that? (I cannot just replace e by 1e since then 1e would be replaced by 11e, so one have to use a regexp match or something like that). – Julia Aug 30 '22 at 04:55
  • 1
    I've added a suggestion to the original question that builds a threshold mode into siunitx directly – Joseph Wright Aug 30 '22 at 10:36

1 Answers1

4

Disclaimer

I don't generally advice to copy and redefine the commands \SI and \num, hence this answer should be taken more as a "this is the way this could be done, even though it shouldn't". siunitx has interfaces to create new commands (or alter the existing ones) which could be used to implement the desired effects of this question. To quote the package author:

one shouldn't copy \num or \SI at all - there is a documented programmers API for siunitx and one should use that to implement modified document commands.


Though I suggest proper input (especially for your e-2 interpreted as 1e-2), the following implements both. I also dropped kvoptions for the key=value interface built into LaTeX since recent versions (falling back to the compatible l3keys2e), and restructured your sty-file a bit.

Package

% threshold.sty
\RequirePackage{expl3,siunitx,etl}
\ProvidesExplPackage{threshold}{2022-08-30}{v0}{custom package mangling siunitx}

\etl_new_replace_once:Nn \julia_threshold_replace_comma:nn { , } \cs_new:Npn \julia_threshold_parse_number:n #1 { \exp_args:Ne \julia_threshold_mayhaps_add_one:n { \julia_threshold_replace_comma:nn {#1} { . } } } \cs_new:Npn \julia_threshold_mayhaps_add_one:n #1 { \tl_if_head_eq_charcode:nNT {#1} e {1} #1 }

\fp_new:N \l_julia_threshold_low_fp \fp_new:N \l_julia_threshold_high_fp

\keys_define:nn { julia/threshold } { low .code:n = \fp_set:Nn \l_julia_threshold_low_fp { \julia_threshold_parse_number:n {#1} } ,low .initial:n = 0.001 ,high .code:n = \fp_set:Nn \l_julia_threshold_high_fp { \julia_threshold_parse_number:n {#1} } ,high .initial:n = 100 }

\cs_if_exist:NTF \ProcessKeyOptions { \ProcessKeyOptions[julia/threshold] } { \RequirePackage{l3keys2e} \ProcessKeysOptions{julia/threshold} }

\NewCommandCopy\OldNum\num \NewCommandCopy\OldSI\SI \sisetup{scientific-notation=true}

\RenewDocumentCommand \num { O{} m } { \fp_compare:nTF { abs ( \julia_threshold_parse_number:n {#2} ) <= \l_julia_threshold_low_fp } { \OldNum[scientific-notation=true, #1] { \julia_threshold_mayhaps_add_one:n {#2} } } { \fp_compare:nTF { abs ( \julia_threshold_parse_number:n {#2} ) >= \l_julia_threshold_high_fp } { \OldNum[scientific-notation=true, #1] { \julia_threshold_mayhaps_add_one:n {#2} } } { \OldNum[scientific-notation=false, #1] { \julia_threshold_mayhaps_add_one:n {#2} } } } }

\RenewDocumentCommand \SI { O{} m m } { \fp_compare:nTF { abs ( \julia_threshold_parse_number:n {#2} ) <= \l_julia_threshold_low_fp } { \OldSI[scientific-notation=true, #1] { \julia_threshold_mayhaps_add_one:n {#2} } {#3} } { \fp_compare:nTF { abs ( \julia_threshold_parse_number:n {#2} ) >= \l_julia_threshold_high_fp } { \OldSI[scientific-notation=true, #1] { \julia_threshold_mayhaps_add_one:n {#2} } {#3} } { \OldSI[scientific-notation=false, #1] { \julia_threshold_mayhaps_add_one:n {#2} } {#3} } } }

\NewDocumentCommand \thresholdsetup { m } { \set_keys:nn { julia/threshold } {#1} }

Document

\documentclass[a4paper,12pt]{article}

\usepackage[locale=DE,per-mode=fraction,round-pad=false]{siunitx}

\usepackage[low=1e-2,high=1e3]{threshold}

\begin{document} \SI{5.2}{m} works but \SI{5,2}{m} and \SI{e-2}{m} not. \end{document}

Result

enter image description here

Skillmon
  • 60,462
  • 3
    I know you know this, but really one shouldn't copy \num or \SI at all - there is a documented programmers API for siunitx and one should use that to implement modified document commands. – Joseph Wright Aug 30 '22 at 08:06
  • @Skillmon: Thanks a lot again. Just as I wanted to accept the answer I have seen Joseph Wright's comment and that he added another solution to the original question here which also seems to be compatible with comma and e. So I am not sure, if it's a good idea to accept your answer. – Julia Aug 30 '22 at 11:01
  • @Julia I'm not on a hunt for ticks (as long as egreg doesn't get the tick instead of me :P), just "accept" the answer you think answers your question best, or none if your requirements aren't fulfilled by any, or none if you intend to wait for another better answer, or tick and then later tick another answer if one pops up. – Skillmon Aug 30 '22 at 11:08