Automatically convert a number to use the correct SI unit prefixOmit zeros before the decimal point and...

Needle Hotend for nonplanar printing

Is there a nice way to assign std::minmax(a, b) to std::tie(a, b)?

Could human civilization live 150 years in a nuclear-powered aircraft carrier colony without resorting to mass killing/ cannibalism?

How exactly is a normal force exerted, at the molecular level?

What could a reptilian race tell by candling their eggs?

Was it really unprofessional of me to leave without asking for a raise first?

How can a valley surrounded by mountains be fertile and rainy?

Is there any problem with this camera not having a lens cover?

Are there any features that help with the roll to avoid the destruction of a Wand of Fireballs when using the last charge?

Details of video memory access arbitration in Space Invaders

Does Anosov geodesic flow imply asphericity?

Where can I get macOS Catalina Beta version?

Why did this meteor appear cyan?

Which resurrection spells are valid to use with the Zealot's 'Warrior of the Gods' Feature?

Can I ask to speak to my future colleagues before accepting an offer?

The Confused Alien

How did installing this RPM create a file?

Most importants new papers in computational complexity

Prime parity peregrination

Can a US President have someone sent to prison?

Should I report a leak of confidential HR information?

Mean Value Theorem: Continuous or Defined?

Do I have to roll to maintain concentration if a target other than me who is affected by my concentration spell takes damage?

Questions about authorship rank and academic politics



Automatically convert a number to use the correct SI unit prefix


Omit zeros before the decimal point and convert scientific notation in siunitx/pgfmathScientific Notation Only For Large NumbersHow can I align numerical and angle values in a table using siunitx?How much space between number and unit?Preserving thousands separator with siunitxPrefix with no unit with siunitxVarious issues with siunitx's option exponent-to-prefixExtending maples latex function to support siunitxsiunitx, exponent-color & hectare - arAutomatically recognize unit prefix in siunitx






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}







4















Say one is talking about numbers 10^6, 10^7, 10^8, 10^9 and so forth one can also write them as 1M, 10M, 100M,1G, with their corresponding SI unit prefixes.



Is there a way to convert a number on the form



 10000000...
1E6
1E-6
-100000...


To a number with SI unit prefixes automatically?



------------------------------------
Input | Output
------------------------------------
prefix{1000000} | 1M
prefix{10000000} | 10M
prefix{100000000} | 100M
prefix{1000000000} | 1G
prefix{1E6} | 1M
prefix{-1E6} | 1μ
------------------------------------









share|improve this question

























  • Can you give a sample of what you hope the usage syntax should look like?

    – Steven B. Segletes
    11 hours ago











  • Done. I added an example

    – N3buchadnezzar
    10 hours ago











  • Thanks. I was just wondering if it has to interact with siunitx calls in a prescribed way, or is what you are showing in your example sufficient?

    – Steven B. Segletes
    10 hours ago






  • 1





    No interaction needed.

    – N3buchadnezzar
    10 hours ago






  • 1





    @PhelypeOleinik My understanding is that the application is specifically for powers of 10 only, though the OP can correct me.

    – Steven B. Segletes
    8 hours ago


















4















Say one is talking about numbers 10^6, 10^7, 10^8, 10^9 and so forth one can also write them as 1M, 10M, 100M,1G, with their corresponding SI unit prefixes.



Is there a way to convert a number on the form



 10000000...
1E6
1E-6
-100000...


To a number with SI unit prefixes automatically?



------------------------------------
Input | Output
------------------------------------
prefix{1000000} | 1M
prefix{10000000} | 10M
prefix{100000000} | 100M
prefix{1000000000} | 1G
prefix{1E6} | 1M
prefix{-1E6} | 1μ
------------------------------------









share|improve this question

























  • Can you give a sample of what you hope the usage syntax should look like?

    – Steven B. Segletes
    11 hours ago











  • Done. I added an example

    – N3buchadnezzar
    10 hours ago











  • Thanks. I was just wondering if it has to interact with siunitx calls in a prescribed way, or is what you are showing in your example sufficient?

    – Steven B. Segletes
    10 hours ago






  • 1





    No interaction needed.

    – N3buchadnezzar
    10 hours ago






  • 1





    @PhelypeOleinik My understanding is that the application is specifically for powers of 10 only, though the OP can correct me.

    – Steven B. Segletes
    8 hours ago














4












4








4








Say one is talking about numbers 10^6, 10^7, 10^8, 10^9 and so forth one can also write them as 1M, 10M, 100M,1G, with their corresponding SI unit prefixes.



Is there a way to convert a number on the form



 10000000...
1E6
1E-6
-100000...


To a number with SI unit prefixes automatically?



------------------------------------
Input | Output
------------------------------------
prefix{1000000} | 1M
prefix{10000000} | 10M
prefix{100000000} | 100M
prefix{1000000000} | 1G
prefix{1E6} | 1M
prefix{-1E6} | 1μ
------------------------------------









share|improve this question
















Say one is talking about numbers 10^6, 10^7, 10^8, 10^9 and so forth one can also write them as 1M, 10M, 100M,1G, with their corresponding SI unit prefixes.



Is there a way to convert a number on the form



 10000000...
1E6
1E-6
-100000...


To a number with SI unit prefixes automatically?



------------------------------------
Input | Output
------------------------------------
prefix{1000000} | 1M
prefix{10000000} | 10M
prefix{100000000} | 100M
prefix{1000000000} | 1G
prefix{1E6} | 1M
prefix{-1E6} | 1μ
------------------------------------






siunitx number






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 10 hours ago









0xC0000022L

2953 silver badges17 bronze badges




2953 silver badges17 bronze badges










asked 11 hours ago









N3buchadnezzarN3buchadnezzar

4,4775 gold badges42 silver badges95 bronze badges




4,4775 gold badges42 silver badges95 bronze badges













  • Can you give a sample of what you hope the usage syntax should look like?

    – Steven B. Segletes
    11 hours ago











  • Done. I added an example

    – N3buchadnezzar
    10 hours ago











  • Thanks. I was just wondering if it has to interact with siunitx calls in a prescribed way, or is what you are showing in your example sufficient?

    – Steven B. Segletes
    10 hours ago






  • 1





    No interaction needed.

    – N3buchadnezzar
    10 hours ago






  • 1





    @PhelypeOleinik My understanding is that the application is specifically for powers of 10 only, though the OP can correct me.

    – Steven B. Segletes
    8 hours ago



















  • Can you give a sample of what you hope the usage syntax should look like?

    – Steven B. Segletes
    11 hours ago











  • Done. I added an example

    – N3buchadnezzar
    10 hours ago











  • Thanks. I was just wondering if it has to interact with siunitx calls in a prescribed way, or is what you are showing in your example sufficient?

    – Steven B. Segletes
    10 hours ago






  • 1





    No interaction needed.

    – N3buchadnezzar
    10 hours ago






  • 1





    @PhelypeOleinik My understanding is that the application is specifically for powers of 10 only, though the OP can correct me.

    – Steven B. Segletes
    8 hours ago

















Can you give a sample of what you hope the usage syntax should look like?

– Steven B. Segletes
11 hours ago





Can you give a sample of what you hope the usage syntax should look like?

– Steven B. Segletes
11 hours ago













Done. I added an example

– N3buchadnezzar
10 hours ago





Done. I added an example

– N3buchadnezzar
10 hours ago













Thanks. I was just wondering if it has to interact with siunitx calls in a prescribed way, or is what you are showing in your example sufficient?

– Steven B. Segletes
10 hours ago





Thanks. I was just wondering if it has to interact with siunitx calls in a prescribed way, or is what you are showing in your example sufficient?

– Steven B. Segletes
10 hours ago




1




1





No interaction needed.

– N3buchadnezzar
10 hours ago





No interaction needed.

– N3buchadnezzar
10 hours ago




1




1





@PhelypeOleinik My understanding is that the application is specifically for powers of 10 only, though the OP can correct me.

– Steven B. Segletes
8 hours ago





@PhelypeOleinik My understanding is that the application is specifically for powers of 10 only, though the OP can correct me.

– Steven B. Segletes
8 hours ago










3 Answers
3






active

oldest

votes


















3














EDITED to solve both input forms. EDITED so that either capital or lowercase E is permitted in the scientific notation (e.g., 1E6 or 1e6).



EDITED to automatically discern multipliers of 1, 10 or 100 on standard units.



If the prefix is outside the range of 1E-24 to 1E26, a ?? is output.



See SUPPLEMENT for more general use of multipliers (outside of 1, 10, 100).



As this answer has expanded with EDITS, let me explan the logic. There are 3 macros that call each other in sequence. Let me work my way from the end to the beginning. The lowest level macro is



prefixSN[<multiplier>]{1E<SI-prefix-integer>}


The multiplier defaults to 1, but can be 10 or 100. The SI-prefix-integer are specific integers for which an SI prefix is defined (-24, -21, ...-6, -3, -2, -1, 0, 1, 2, 3, 6, ...21, 24). If the provided integer is not in this list, a ?? is output. If the integer is in the list, the appropriate SI-prefix is output following the multiplier.



The macro that feeds prefixSN in the proper syntax is called prefixmult, with syntax



prefixmult{1E<integer>}


Here integer should be in the range -24 to 26. Based on the value of the integer, it sets the prefix as 1, 10, or 100, and adjusts the integer to the next lower SI standard value. For example if the input to prefixmult was 1E5, it would set the call prefixSI[100]{1E3}.



The top-level macro, prefix, which feeds prefixmult its integer format, can take input in four possible form s:



prefix{1E<integer>}
prefix{1e<integer>}
prefix{10<...>0}
prefix{.0<...>01}


It sorts through looking for an E or e. Finding one, it passes the capital-E form to prefixmult with the associated integer. If no E is found, it looks for a decimal point, a 1 and multiple 0 tokens. Based on what it finds, it reconstructs the associated integer based on the number of zeros and passes it onto prefixmult.



Here is the MWE.



documentclass{article}
usepackage{siunitx,listofitems}
newcommandprefixSN[2][1]{#1,prefixSNaux#2relax}
defprefixSNaux 1E#1relax{%
ifnum#1=0relaxelse
ifnum#1=-1relaxtextrm{d}else
ifnum#1=-2relaxtextrm{c}else
ifnum#1=-3relaxtextrm{m}else
ifnum#1=-6relaxtextrm{ensuremath{mu}}else
ifnum#1=-9relaxtextrm{n}else
ifnum#1=-12relaxtextrm{p}else
ifnum#1=-15relaxtextrm{f}else
ifnum#1=-18relaxtextrm{a}else
ifnum#1=-21relaxtextrm{z}else
ifnum#1=-24relaxtextrm{y}else
ifnum#1=1relaxtextrm{da}else
ifnum#1=2relaxtextrm{h}else
ifnum#1=3relaxtextrm{k}else
ifnum#1=6relaxtextrm{M}else
ifnum#1=9relaxtextrm{G}else
ifnum#1=12relaxtextrm{T}else
ifnum#1=15relaxtextrm{P}else
ifnum#1=18relaxtextrm{E}else
ifnum#1=21relaxtextrm{Z}else
ifnum#1=24relaxtextrm{Y}else
??%
fififififififififififififififififififififi
}
newcommandprefix[1]{%
setsepchar{1E||1e}%
readlistscinot{#1}%
ifnumscinotlen>1relax
itemtomacroscinot[2]temp%
expandafterprefixmultexpandafter{expandafter1expandafter Etemp}%
else
setsepchar{./1/0}%
readlistzerocount{#1}%
ifnumzerocountlen=1relax
expandafterprefixmultexpandafter{expandafter1expandafter E%
thenumexprlistlenzerocount[1,2]-1relax}%
else
expandafterprefixmultexpandafter{expandafter1expandafter E%
expandafter-thenumexprlistlenzerocount[2,1]relax}%
fi
fi
}
newcommandprefixmult[1]{prefixmultaux#1relax}
defprefixmultaux 1E#1relax{%
setsepchar{E4||E7||E10||E13||E16||E19||E22||E25||%
E-5||E-8||E-11||E-14||E-17||E-20||E-23}%
readlistfactormult{E#1}%
ifnumfactormultlen>1relax
prefixSN[10]{1Ethenumexpr#1-1relax}
else
setsepchar{E5||E8||E11||E14||E17||E20||E23||E26||%
E-4||E-7||E-10||E-13||E-16||E-19||E-22}%
readlistfactormult{E#1}%
ifnumfactormultlen>1relax
prefixSN[100]{1Ethenumexpr#1-2relax}
else
prefixSN[1]{1E#1}%
fi
fi
}
begin{document}
prefix{1E6}par
prefix{1E-15}par
prefix{1e-6}par
prefix{100}par
prefix{1000000}par
prefix{.001}par
prefix{.000001}par
prefix{1E5}par
prefix{10000}par
prefix{.0001}par
prefix{1E7}par
prefix{1E-5}par
prefix{1E8}par
prefix{1E-4}
end{document}


enter image description here



SUPPLEMENT



Not sure if this is an improvement, as it seems to me that the prefix should deal solely in powers of 10. However, if one wished for a more general implementation that could handle any multiplier of a single significant digit, then here it is:



documentclass{article}
usepackage{siunitx,listofitems}
newcommandprefixSN[2][1]{#1,prefixSNaux#2relax}
defprefixSNaux 1E#1relax{%
ifnum#1=0relaxelse
ifnum#1=-1relaxtextrm{d}else
ifnum#1=-2relaxtextrm{c}else
ifnum#1=-3relaxtextrm{m}else
ifnum#1=-6relaxtextrm{ensuremath{mu}}else
ifnum#1=-9relaxtextrm{n}else
ifnum#1=-12relaxtextrm{p}else
ifnum#1=-15relaxtextrm{f}else
ifnum#1=-18relaxtextrm{a}else
ifnum#1=-21relaxtextrm{z}else
ifnum#1=-24relaxtextrm{y}else
ifnum#1=1relaxtextrm{da}else
ifnum#1=2relaxtextrm{h}else
ifnum#1=3relaxtextrm{k}else
ifnum#1=6relaxtextrm{M}else
ifnum#1=9relaxtextrm{G}else
ifnum#1=12relaxtextrm{T}else
ifnum#1=15relaxtextrm{P}else
ifnum#1=18relaxtextrm{E}else
ifnum#1=21relaxtextrm{Z}else
ifnum#1=24relaxtextrm{Y}else
??%
fififififififififififififififififififififi
}
newcommandprefix[1]{%
setsepchar{E||e}%
readlistscinot{#1}%
ifnumscinotlen>1relax
itemtomacroscinot[1]premult%
itemtomacroscinot[2]temp%
expandafterexpandafterexpandafterprefixmult
expandafterexpandafterexpandafter{%
expandafterpremultexpandafter Etemp}%
else
setsepchar{./1||2||3||4||5||6||7||8||9/0}%
readlistzerocount{#1}%
ifnumzerocountlen=1relax
expandafterexpandafterexpandafterdef
expandafterexpandafterexpandaftertemp
expandafterexpandafterexpandafter{zerocountsep[1,1]}%
expandafterexpandafterexpandafterprefixmult
expandafterexpandafterexpandafter{%
expandaftertempexpandafter E%
thenumexprlistlenzerocount[1,2]-1relax}%
else
expandafterexpandafterexpandafterdef
expandafterexpandafterexpandaftertemp
expandafterexpandafterexpandafter{zerocountsep[2,1]}%
expandafterexpandafterexpandafterprefixmult
expandafterexpandafterexpandafter{%
expandaftertempexpandafter E%
expandafter-thenumexprlistlenzerocount[2,1]relax}%
fi
fi
}
newcommandprefixmult[1]{prefixmultaux#1relax}
defprefixmultaux #1E#2relax{%
setsepchar{E4||E7||E10||E13||E16||E19||E22||E25||%
E-5||E-8||E-11||E-14||E-17||E-20||E-23}%
readlistfactormult{E#2}%
ifnumfactormultlen>1relax
prefixSN[#10]{1Ethenumexpr#2-1relax}
else
setsepchar{E5||E8||E11||E14||E17||E20||E23||E26||%
E-4||E-7||E-10||E-13||E-16||E-19||E-22}%
readlistfactormult{E#2}%
ifnumfactormultlen>1relax
prefixSN[#100]{1Ethenumexpr#2-2relax}
else
prefixSN[#1]{1E#2}%
fi
fi
}
begin{document}
prefix{4E6}par
prefix{1E-15}par
prefix{1e-6}par
prefix{300}par
prefix{1000000}par
prefix{.001}par
prefix{.000004}par
prefix{1E5}par
prefix{10000}par
prefix{.0001}par
prefix{5E7}par
prefix{1E-5}par
prefix{3E8}par
prefix{1E-4}
end{document}


enter image description here






share|improve this answer


























  • Awesome! Now all that remains is for someone to figure out how to convert prefix{10000} to 10k =)

    – N3buchadnezzar
    10 hours ago






  • 1





    @N3buchadnezzar Ask and ye shall receive. Done.

    – Steven B. Segletes
    9 hours ago



















2














This supports both exponential and standard notation.



No check about the nonzero digit is performed, the input is assumed to be of the form



1<sequence of zeros>
-1<sequence of zeros>
1e<exponent>
1E<exponent>
-1e<exponent>
-1E<exponent>


The range is -1E-26 to 1E26. Numbers outside this range silently fail. You can add control about the range.



Here's the code: note that the bulk of the work is performed by __nebuch_prefix_exp:nn (precisely by the :ee variant).



documentclass{article}
usepackage{siunitx} % also loads xparse and expl3

ExplSyntaxOn
NewDocumentCommand{prefix}{m}
{
nebuch_prefix:e { tl_lower_case:n { #1 } }
}

seq_new:N l__nebuch_prefix_input_seq

cs_new_protected:Nn nebuch_prefix:n
{
seq_set_split:Nnn l__nebuch_prefix_input_seq { e } { #1 }
int_compare:nTF { seq_count:N l__nebuch_prefix_input_seq > 1 }
{% there was e/E
__nebuch_prefix_exp:ee
{ seq_item:Nn l__nebuch_prefix_input_seq { 1 } }
{ seq_item:Nn l__nebuch_prefix_input_seq { 2 } }
}
{% no e/E
__nebuch_prefix_long:n { #1 }
}
}
cs_generate_variant:Nn nebuch_prefix:n { e }

cs_new_protected:Nn __nebuch_prefix_exp:nn
{
int_compare:nTF { int_mod:nn { #2 } { 3 } < 0 }
{
__nebuch_prefix_exp:ee
{ #1 prg_replicate:nn { 3 + int_mod:nn { #2 } { 3 } } { 0 } }
{ int_eval:n { #2 - 3 - int_mod:nn { #2 } { 3 } } }
}
{
SI
{
#1 % 1 or -1
prg_replicate:nn { int_mod:nn { #2 } { 3 } } { 0 }
}
{
int_case:nn { int_div_truncate:nn { #2 } { 3 } }
{
{-8}{yoctovoidunit}
{-7}{zeptovoidunit}
{-6}{attovoidunit}
{-5}{femtovoidunit}
{-4}{picovoidunit}
{-3}{nanovoidunit}
{-2}{microvoidunit}
{-1}{millivoidunit}
{0}{!voidunit}
{1}{kilovoidunit}
{2}{megavoidunit}
{3}{gigavoidunit}
{4}{teravoidunit}
{5}{petavoidunit}
{6}{exavoidunit}
{7}{zettavoidunit}
{8}{yottavoidunit}
}
}
}
}
cs_generate_variant:Nn __nebuch_prefix_exp:nn {ee}

cs_new_protected:Nn __nebuch_prefix_long:n
{
% count the number of zeros
regex_split:nnN { (-*1+) } { #1 } l__nebuch_prefix_input_seq
__nebuch_prefix_exp:ee
{ seq_item:Nn l__nebuch_prefix_input_seq { 2 } }
{ tl_count:e { seq_item:Nn l__nebuch_prefix_input_seq { 3 } } }
}
cs_generate_variant:Nn tl_count:n { e }
ExplSyntaxOff

DeclareSIUnit{voidunit}{relax}

begin{document}

prefix{1e0}

prefix{1e2}

prefix{1E4}

prefix{-1E20}

prefix{1}

prefix{10}

prefix{100}

prefix{1000}

prefix{10000}

prefix{100000}

prefix{1000000}

prefix{10000000}

prefix{100000000}

prefix{1000000000}

prefix{-10000000000}

prefix{100000000000}

prefix{1E6}

prefix{1E24}

prefix{-1E-6}

prefix{1E-8}

prefix{-1E-7}

end{document}


enter image description here






share|improve this answer































    1














    This allows any (valid, of course) value or expression to be input. The code (ab)uses the LaTeX3 floating point unit to parse the input expression and convert it to exponential notation. With that the code just looks for the correct prefix to apply to that number. Numbers outside the range are printed with more digits to make the number fit the nearest prefix (i.e., 1E28 prints 10000 Y and 1E-28 prints 0.0001 y).



    The prefix macro (which should probably be called postfix :-) is expandable, takes one argument, the number, and prints the it followed by the prefix.



    The prefixSI macro is not expandable and has the same signature as siunitx's SI macro. prefixSI evaluates its first mandatory argument with prefix (nebu_prefix:n, actually), as described above, and passes it to SI. The selected prefix is stored in prefix (inside a group, so that the macro prefix can be used agian) which can be used in an unit expression, for example prefixSI{1000}{prefixmetre} prints 1 km.



    Prefixes can be declared with setprefix <siunitx prefix macro> { <prefix> } { <value> }, like setprefix centi { c } { -2 }. Make sure that the <siunitx prefix macro> exists. If you're not going to use prefixSI then you can use relax there.



    documentclass{article}
    usepackage{siunitx}
    ExplSyntaxOn
    % Internals
    int_new:N l__nebu_min_prefix_int
    tl_new:N l__nebu_base_number_tl
    tl_new:N l__nebu_mode_tl
    cs_new:Npn nebu_prefix:n #1
    {
    exp_args:Nf __nebu_prefix:n
    { exp_args:Nf fp_to_scientific:n { tl_lower_case:n {#1} } }
    }
    cs_new:Npn __nebu_prefix:n #1
    { __nebu_prefix:nwnw #1 q_stop }
    cs_new:Npn __nebu_prefix:nwnw #1 e #2 q_stop
    { __nebu_find_prefix:nnn {#2} {#1} {1} }
    cs_new:Npn __nebu_find_prefix:nnn #1 #2 #3
    {
    tl_if_exist:cT { l__nebu_ #1 tl_use:N l__nebu_mode_tl _prefix_tl }
    {
    use_i_delimit_by_q_stop:nw
    { __nebu_output:nnn {#2} {#1} {#3} }
    }
    int_compare:nNnT {#1} < l__nebu_min_prefix_int
    {
    use_i_delimit_by_q_stop:nw
    {
    exp_args:Nf __nebu_find_prefix:nnn
    { int_eval:n {#1+1} } {#2} {#3/10}
    }
    }
    use_i:nn
    {
    exp_args:Nf __nebu_find_prefix:nnn
    { int_eval:n {#1-1} } {#2} {#3*10}
    }
    q_stop
    }
    exp_args_generate:n { fv }
    cs_new:Npn __nebu_output:nnn #1 #2 #3
    {
    exp_args:Nfv nebu_output:nn
    { fp_to_decimal:n {#1*#3} } { l__nebu_ #2 tl_use:N l__nebu_mode_tl _prefix_tl }
    }
    cs_new_protected:Npn nebu_prefix_set:Nnn #1 #2 #3
    {
    exp_args:Nxx __nebu_prefix_set:nnN
    { tl_trim_spaces:n {#2} } { int_eval:n {#3} } #1
    }
    cs_new_protected:Npn __nebu_prefix_set:nnN #1 #2 #3
    {
    tl_clear_new:c { l__nebu_ #2 _prefix_tl }
    tl_clear_new:c { l__nebu_ #2 _siunitx_prefix_tl }
    tl_set:cn { l__nebu_ #2 _prefix_tl } {#1}
    tl_set:cn { l__nebu_ #2 _siunitx_prefix_tl } {#3}
    int_set:Nn l__nebu_min_prefix_int { int_min:nn {#2} { l__nebu_min_prefix_int } }
    }
    % User interface
    NewExpandableDocumentCommand prefix { m }
    { nebu_prefix:n {#1} }
    cs_new:Npn nebu_output:nn #1 #2 { #1, textrm{#2} }
    NewDocumentCommand setprefix { m m m }
    { nebu_prefix_set:Nnn #1 {#2} {#3} }
    DeclareSIPrefix none { } { 0 }
    setprefix none { } { 0 }
    %
    cs_new_protected:Npn __nebu_store:nn #1 #2
    {
    tl_set:Nn l__nebu_base_number_tl {#1}
    cs_set:Npn prefix {#2}
    }
    NewExpandableDocumentCommand prefixSI { o m o m }
    {
    group_begin:
    cs_set_eq:NN nebu_output:nn __nebu_store:nn
    tl_set:Nn l__nebu_mode_tl { _siunitx }
    nebu_prefix:n {#2}
    SI [#1] { l__nebu_base_number_tl } [#3] {#4}
    group_end:
    }
    ExplSyntaxOff

    setprefix yocto { y } { -24 }
    setprefix zepto { z } { -21 }
    setprefix atto { a } { -18 }
    setprefix femto { f } { -15 }
    setprefix pico { p } { -12 }
    setprefix nano { n } { -9 }
    setprefix micro { SIUnitSymbolMicro } { -6 }
    setprefix milli { m } { -3 }
    setprefix centi { c } { -2 }
    setprefix deci { d } { -1 }
    setprefix deca { da } { 1 }
    setprefix hecto { h } { 2 }
    setprefix kilo { k } { 3 }
    setprefix mega { M } { 6 }
    setprefix giga { G } { 9 }
    setprefix tera { T } { 12 }
    setprefix peta { P } { 15 }
    setprefix exa { E } { 18 }
    setprefix zetta { Z } { 21 }
    setprefix yotta { Y } { 24 }

    begin{document}
    prefix{1}par
    prefix{4E6}par
    prefix{1E-15}par
    prefix{1e-6}par
    prefix{300}par
    prefix{1000000}par
    prefix{.001}par
    prefix{.000004}par
    prefix{1E5}par
    prefix{10000}par
    prefix{.0001}par
    prefix{5E7}par
    prefix{1E-5}par
    prefix{3E8}par
    prefix{1E-4}par
    prefix{1E-24}par
    prefix{1E-28}par
    prefix{1E24}par
    prefix{1E28}par
    prefix{1e3*pi}par
    prefixSI{1e3*pi}{prefixmetre}par
    end{document}



    enter image description here







    share|improve this answer


























    • How would 10E-4 metres look? ;-) Great answer!

      – N3buchadnezzar
      6 hours ago






    • 1





      @N3buchadnezzar Thanks! A millimetre: 1 mm? Is there something wrong?

      – Phelype Oleinik
      6 hours ago














    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
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f497228%2fautomatically-convert-a-number-to-use-the-correct-si-unit-prefix%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









    3














    EDITED to solve both input forms. EDITED so that either capital or lowercase E is permitted in the scientific notation (e.g., 1E6 or 1e6).



    EDITED to automatically discern multipliers of 1, 10 or 100 on standard units.



    If the prefix is outside the range of 1E-24 to 1E26, a ?? is output.



    See SUPPLEMENT for more general use of multipliers (outside of 1, 10, 100).



    As this answer has expanded with EDITS, let me explan the logic. There are 3 macros that call each other in sequence. Let me work my way from the end to the beginning. The lowest level macro is



    prefixSN[<multiplier>]{1E<SI-prefix-integer>}


    The multiplier defaults to 1, but can be 10 or 100. The SI-prefix-integer are specific integers for which an SI prefix is defined (-24, -21, ...-6, -3, -2, -1, 0, 1, 2, 3, 6, ...21, 24). If the provided integer is not in this list, a ?? is output. If the integer is in the list, the appropriate SI-prefix is output following the multiplier.



    The macro that feeds prefixSN in the proper syntax is called prefixmult, with syntax



    prefixmult{1E<integer>}


    Here integer should be in the range -24 to 26. Based on the value of the integer, it sets the prefix as 1, 10, or 100, and adjusts the integer to the next lower SI standard value. For example if the input to prefixmult was 1E5, it would set the call prefixSI[100]{1E3}.



    The top-level macro, prefix, which feeds prefixmult its integer format, can take input in four possible form s:



    prefix{1E<integer>}
    prefix{1e<integer>}
    prefix{10<...>0}
    prefix{.0<...>01}


    It sorts through looking for an E or e. Finding one, it passes the capital-E form to prefixmult with the associated integer. If no E is found, it looks for a decimal point, a 1 and multiple 0 tokens. Based on what it finds, it reconstructs the associated integer based on the number of zeros and passes it onto prefixmult.



    Here is the MWE.



    documentclass{article}
    usepackage{siunitx,listofitems}
    newcommandprefixSN[2][1]{#1,prefixSNaux#2relax}
    defprefixSNaux 1E#1relax{%
    ifnum#1=0relaxelse
    ifnum#1=-1relaxtextrm{d}else
    ifnum#1=-2relaxtextrm{c}else
    ifnum#1=-3relaxtextrm{m}else
    ifnum#1=-6relaxtextrm{ensuremath{mu}}else
    ifnum#1=-9relaxtextrm{n}else
    ifnum#1=-12relaxtextrm{p}else
    ifnum#1=-15relaxtextrm{f}else
    ifnum#1=-18relaxtextrm{a}else
    ifnum#1=-21relaxtextrm{z}else
    ifnum#1=-24relaxtextrm{y}else
    ifnum#1=1relaxtextrm{da}else
    ifnum#1=2relaxtextrm{h}else
    ifnum#1=3relaxtextrm{k}else
    ifnum#1=6relaxtextrm{M}else
    ifnum#1=9relaxtextrm{G}else
    ifnum#1=12relaxtextrm{T}else
    ifnum#1=15relaxtextrm{P}else
    ifnum#1=18relaxtextrm{E}else
    ifnum#1=21relaxtextrm{Z}else
    ifnum#1=24relaxtextrm{Y}else
    ??%
    fififififififififififififififififififififi
    }
    newcommandprefix[1]{%
    setsepchar{1E||1e}%
    readlistscinot{#1}%
    ifnumscinotlen>1relax
    itemtomacroscinot[2]temp%
    expandafterprefixmultexpandafter{expandafter1expandafter Etemp}%
    else
    setsepchar{./1/0}%
    readlistzerocount{#1}%
    ifnumzerocountlen=1relax
    expandafterprefixmultexpandafter{expandafter1expandafter E%
    thenumexprlistlenzerocount[1,2]-1relax}%
    else
    expandafterprefixmultexpandafter{expandafter1expandafter E%
    expandafter-thenumexprlistlenzerocount[2,1]relax}%
    fi
    fi
    }
    newcommandprefixmult[1]{prefixmultaux#1relax}
    defprefixmultaux 1E#1relax{%
    setsepchar{E4||E7||E10||E13||E16||E19||E22||E25||%
    E-5||E-8||E-11||E-14||E-17||E-20||E-23}%
    readlistfactormult{E#1}%
    ifnumfactormultlen>1relax
    prefixSN[10]{1Ethenumexpr#1-1relax}
    else
    setsepchar{E5||E8||E11||E14||E17||E20||E23||E26||%
    E-4||E-7||E-10||E-13||E-16||E-19||E-22}%
    readlistfactormult{E#1}%
    ifnumfactormultlen>1relax
    prefixSN[100]{1Ethenumexpr#1-2relax}
    else
    prefixSN[1]{1E#1}%
    fi
    fi
    }
    begin{document}
    prefix{1E6}par
    prefix{1E-15}par
    prefix{1e-6}par
    prefix{100}par
    prefix{1000000}par
    prefix{.001}par
    prefix{.000001}par
    prefix{1E5}par
    prefix{10000}par
    prefix{.0001}par
    prefix{1E7}par
    prefix{1E-5}par
    prefix{1E8}par
    prefix{1E-4}
    end{document}


    enter image description here



    SUPPLEMENT



    Not sure if this is an improvement, as it seems to me that the prefix should deal solely in powers of 10. However, if one wished for a more general implementation that could handle any multiplier of a single significant digit, then here it is:



    documentclass{article}
    usepackage{siunitx,listofitems}
    newcommandprefixSN[2][1]{#1,prefixSNaux#2relax}
    defprefixSNaux 1E#1relax{%
    ifnum#1=0relaxelse
    ifnum#1=-1relaxtextrm{d}else
    ifnum#1=-2relaxtextrm{c}else
    ifnum#1=-3relaxtextrm{m}else
    ifnum#1=-6relaxtextrm{ensuremath{mu}}else
    ifnum#1=-9relaxtextrm{n}else
    ifnum#1=-12relaxtextrm{p}else
    ifnum#1=-15relaxtextrm{f}else
    ifnum#1=-18relaxtextrm{a}else
    ifnum#1=-21relaxtextrm{z}else
    ifnum#1=-24relaxtextrm{y}else
    ifnum#1=1relaxtextrm{da}else
    ifnum#1=2relaxtextrm{h}else
    ifnum#1=3relaxtextrm{k}else
    ifnum#1=6relaxtextrm{M}else
    ifnum#1=9relaxtextrm{G}else
    ifnum#1=12relaxtextrm{T}else
    ifnum#1=15relaxtextrm{P}else
    ifnum#1=18relaxtextrm{E}else
    ifnum#1=21relaxtextrm{Z}else
    ifnum#1=24relaxtextrm{Y}else
    ??%
    fififififififififififififififififififififi
    }
    newcommandprefix[1]{%
    setsepchar{E||e}%
    readlistscinot{#1}%
    ifnumscinotlen>1relax
    itemtomacroscinot[1]premult%
    itemtomacroscinot[2]temp%
    expandafterexpandafterexpandafterprefixmult
    expandafterexpandafterexpandafter{%
    expandafterpremultexpandafter Etemp}%
    else
    setsepchar{./1||2||3||4||5||6||7||8||9/0}%
    readlistzerocount{#1}%
    ifnumzerocountlen=1relax
    expandafterexpandafterexpandafterdef
    expandafterexpandafterexpandaftertemp
    expandafterexpandafterexpandafter{zerocountsep[1,1]}%
    expandafterexpandafterexpandafterprefixmult
    expandafterexpandafterexpandafter{%
    expandaftertempexpandafter E%
    thenumexprlistlenzerocount[1,2]-1relax}%
    else
    expandafterexpandafterexpandafterdef
    expandafterexpandafterexpandaftertemp
    expandafterexpandafterexpandafter{zerocountsep[2,1]}%
    expandafterexpandafterexpandafterprefixmult
    expandafterexpandafterexpandafter{%
    expandaftertempexpandafter E%
    expandafter-thenumexprlistlenzerocount[2,1]relax}%
    fi
    fi
    }
    newcommandprefixmult[1]{prefixmultaux#1relax}
    defprefixmultaux #1E#2relax{%
    setsepchar{E4||E7||E10||E13||E16||E19||E22||E25||%
    E-5||E-8||E-11||E-14||E-17||E-20||E-23}%
    readlistfactormult{E#2}%
    ifnumfactormultlen>1relax
    prefixSN[#10]{1Ethenumexpr#2-1relax}
    else
    setsepchar{E5||E8||E11||E14||E17||E20||E23||E26||%
    E-4||E-7||E-10||E-13||E-16||E-19||E-22}%
    readlistfactormult{E#2}%
    ifnumfactormultlen>1relax
    prefixSN[#100]{1Ethenumexpr#2-2relax}
    else
    prefixSN[#1]{1E#2}%
    fi
    fi
    }
    begin{document}
    prefix{4E6}par
    prefix{1E-15}par
    prefix{1e-6}par
    prefix{300}par
    prefix{1000000}par
    prefix{.001}par
    prefix{.000004}par
    prefix{1E5}par
    prefix{10000}par
    prefix{.0001}par
    prefix{5E7}par
    prefix{1E-5}par
    prefix{3E8}par
    prefix{1E-4}
    end{document}


    enter image description here






    share|improve this answer


























    • Awesome! Now all that remains is for someone to figure out how to convert prefix{10000} to 10k =)

      – N3buchadnezzar
      10 hours ago






    • 1





      @N3buchadnezzar Ask and ye shall receive. Done.

      – Steven B. Segletes
      9 hours ago
















    3














    EDITED to solve both input forms. EDITED so that either capital or lowercase E is permitted in the scientific notation (e.g., 1E6 or 1e6).



    EDITED to automatically discern multipliers of 1, 10 or 100 on standard units.



    If the prefix is outside the range of 1E-24 to 1E26, a ?? is output.



    See SUPPLEMENT for more general use of multipliers (outside of 1, 10, 100).



    As this answer has expanded with EDITS, let me explan the logic. There are 3 macros that call each other in sequence. Let me work my way from the end to the beginning. The lowest level macro is



    prefixSN[<multiplier>]{1E<SI-prefix-integer>}


    The multiplier defaults to 1, but can be 10 or 100. The SI-prefix-integer are specific integers for which an SI prefix is defined (-24, -21, ...-6, -3, -2, -1, 0, 1, 2, 3, 6, ...21, 24). If the provided integer is not in this list, a ?? is output. If the integer is in the list, the appropriate SI-prefix is output following the multiplier.



    The macro that feeds prefixSN in the proper syntax is called prefixmult, with syntax



    prefixmult{1E<integer>}


    Here integer should be in the range -24 to 26. Based on the value of the integer, it sets the prefix as 1, 10, or 100, and adjusts the integer to the next lower SI standard value. For example if the input to prefixmult was 1E5, it would set the call prefixSI[100]{1E3}.



    The top-level macro, prefix, which feeds prefixmult its integer format, can take input in four possible form s:



    prefix{1E<integer>}
    prefix{1e<integer>}
    prefix{10<...>0}
    prefix{.0<...>01}


    It sorts through looking for an E or e. Finding one, it passes the capital-E form to prefixmult with the associated integer. If no E is found, it looks for a decimal point, a 1 and multiple 0 tokens. Based on what it finds, it reconstructs the associated integer based on the number of zeros and passes it onto prefixmult.



    Here is the MWE.



    documentclass{article}
    usepackage{siunitx,listofitems}
    newcommandprefixSN[2][1]{#1,prefixSNaux#2relax}
    defprefixSNaux 1E#1relax{%
    ifnum#1=0relaxelse
    ifnum#1=-1relaxtextrm{d}else
    ifnum#1=-2relaxtextrm{c}else
    ifnum#1=-3relaxtextrm{m}else
    ifnum#1=-6relaxtextrm{ensuremath{mu}}else
    ifnum#1=-9relaxtextrm{n}else
    ifnum#1=-12relaxtextrm{p}else
    ifnum#1=-15relaxtextrm{f}else
    ifnum#1=-18relaxtextrm{a}else
    ifnum#1=-21relaxtextrm{z}else
    ifnum#1=-24relaxtextrm{y}else
    ifnum#1=1relaxtextrm{da}else
    ifnum#1=2relaxtextrm{h}else
    ifnum#1=3relaxtextrm{k}else
    ifnum#1=6relaxtextrm{M}else
    ifnum#1=9relaxtextrm{G}else
    ifnum#1=12relaxtextrm{T}else
    ifnum#1=15relaxtextrm{P}else
    ifnum#1=18relaxtextrm{E}else
    ifnum#1=21relaxtextrm{Z}else
    ifnum#1=24relaxtextrm{Y}else
    ??%
    fififififififififififififififififififififi
    }
    newcommandprefix[1]{%
    setsepchar{1E||1e}%
    readlistscinot{#1}%
    ifnumscinotlen>1relax
    itemtomacroscinot[2]temp%
    expandafterprefixmultexpandafter{expandafter1expandafter Etemp}%
    else
    setsepchar{./1/0}%
    readlistzerocount{#1}%
    ifnumzerocountlen=1relax
    expandafterprefixmultexpandafter{expandafter1expandafter E%
    thenumexprlistlenzerocount[1,2]-1relax}%
    else
    expandafterprefixmultexpandafter{expandafter1expandafter E%
    expandafter-thenumexprlistlenzerocount[2,1]relax}%
    fi
    fi
    }
    newcommandprefixmult[1]{prefixmultaux#1relax}
    defprefixmultaux 1E#1relax{%
    setsepchar{E4||E7||E10||E13||E16||E19||E22||E25||%
    E-5||E-8||E-11||E-14||E-17||E-20||E-23}%
    readlistfactormult{E#1}%
    ifnumfactormultlen>1relax
    prefixSN[10]{1Ethenumexpr#1-1relax}
    else
    setsepchar{E5||E8||E11||E14||E17||E20||E23||E26||%
    E-4||E-7||E-10||E-13||E-16||E-19||E-22}%
    readlistfactormult{E#1}%
    ifnumfactormultlen>1relax
    prefixSN[100]{1Ethenumexpr#1-2relax}
    else
    prefixSN[1]{1E#1}%
    fi
    fi
    }
    begin{document}
    prefix{1E6}par
    prefix{1E-15}par
    prefix{1e-6}par
    prefix{100}par
    prefix{1000000}par
    prefix{.001}par
    prefix{.000001}par
    prefix{1E5}par
    prefix{10000}par
    prefix{.0001}par
    prefix{1E7}par
    prefix{1E-5}par
    prefix{1E8}par
    prefix{1E-4}
    end{document}


    enter image description here



    SUPPLEMENT



    Not sure if this is an improvement, as it seems to me that the prefix should deal solely in powers of 10. However, if one wished for a more general implementation that could handle any multiplier of a single significant digit, then here it is:



    documentclass{article}
    usepackage{siunitx,listofitems}
    newcommandprefixSN[2][1]{#1,prefixSNaux#2relax}
    defprefixSNaux 1E#1relax{%
    ifnum#1=0relaxelse
    ifnum#1=-1relaxtextrm{d}else
    ifnum#1=-2relaxtextrm{c}else
    ifnum#1=-3relaxtextrm{m}else
    ifnum#1=-6relaxtextrm{ensuremath{mu}}else
    ifnum#1=-9relaxtextrm{n}else
    ifnum#1=-12relaxtextrm{p}else
    ifnum#1=-15relaxtextrm{f}else
    ifnum#1=-18relaxtextrm{a}else
    ifnum#1=-21relaxtextrm{z}else
    ifnum#1=-24relaxtextrm{y}else
    ifnum#1=1relaxtextrm{da}else
    ifnum#1=2relaxtextrm{h}else
    ifnum#1=3relaxtextrm{k}else
    ifnum#1=6relaxtextrm{M}else
    ifnum#1=9relaxtextrm{G}else
    ifnum#1=12relaxtextrm{T}else
    ifnum#1=15relaxtextrm{P}else
    ifnum#1=18relaxtextrm{E}else
    ifnum#1=21relaxtextrm{Z}else
    ifnum#1=24relaxtextrm{Y}else
    ??%
    fififififififififififififififififififififi
    }
    newcommandprefix[1]{%
    setsepchar{E||e}%
    readlistscinot{#1}%
    ifnumscinotlen>1relax
    itemtomacroscinot[1]premult%
    itemtomacroscinot[2]temp%
    expandafterexpandafterexpandafterprefixmult
    expandafterexpandafterexpandafter{%
    expandafterpremultexpandafter Etemp}%
    else
    setsepchar{./1||2||3||4||5||6||7||8||9/0}%
    readlistzerocount{#1}%
    ifnumzerocountlen=1relax
    expandafterexpandafterexpandafterdef
    expandafterexpandafterexpandaftertemp
    expandafterexpandafterexpandafter{zerocountsep[1,1]}%
    expandafterexpandafterexpandafterprefixmult
    expandafterexpandafterexpandafter{%
    expandaftertempexpandafter E%
    thenumexprlistlenzerocount[1,2]-1relax}%
    else
    expandafterexpandafterexpandafterdef
    expandafterexpandafterexpandaftertemp
    expandafterexpandafterexpandafter{zerocountsep[2,1]}%
    expandafterexpandafterexpandafterprefixmult
    expandafterexpandafterexpandafter{%
    expandaftertempexpandafter E%
    expandafter-thenumexprlistlenzerocount[2,1]relax}%
    fi
    fi
    }
    newcommandprefixmult[1]{prefixmultaux#1relax}
    defprefixmultaux #1E#2relax{%
    setsepchar{E4||E7||E10||E13||E16||E19||E22||E25||%
    E-5||E-8||E-11||E-14||E-17||E-20||E-23}%
    readlistfactormult{E#2}%
    ifnumfactormultlen>1relax
    prefixSN[#10]{1Ethenumexpr#2-1relax}
    else
    setsepchar{E5||E8||E11||E14||E17||E20||E23||E26||%
    E-4||E-7||E-10||E-13||E-16||E-19||E-22}%
    readlistfactormult{E#2}%
    ifnumfactormultlen>1relax
    prefixSN[#100]{1Ethenumexpr#2-2relax}
    else
    prefixSN[#1]{1E#2}%
    fi
    fi
    }
    begin{document}
    prefix{4E6}par
    prefix{1E-15}par
    prefix{1e-6}par
    prefix{300}par
    prefix{1000000}par
    prefix{.001}par
    prefix{.000004}par
    prefix{1E5}par
    prefix{10000}par
    prefix{.0001}par
    prefix{5E7}par
    prefix{1E-5}par
    prefix{3E8}par
    prefix{1E-4}
    end{document}


    enter image description here






    share|improve this answer


























    • Awesome! Now all that remains is for someone to figure out how to convert prefix{10000} to 10k =)

      – N3buchadnezzar
      10 hours ago






    • 1





      @N3buchadnezzar Ask and ye shall receive. Done.

      – Steven B. Segletes
      9 hours ago














    3












    3








    3







    EDITED to solve both input forms. EDITED so that either capital or lowercase E is permitted in the scientific notation (e.g., 1E6 or 1e6).



    EDITED to automatically discern multipliers of 1, 10 or 100 on standard units.



    If the prefix is outside the range of 1E-24 to 1E26, a ?? is output.



    See SUPPLEMENT for more general use of multipliers (outside of 1, 10, 100).



    As this answer has expanded with EDITS, let me explan the logic. There are 3 macros that call each other in sequence. Let me work my way from the end to the beginning. The lowest level macro is



    prefixSN[<multiplier>]{1E<SI-prefix-integer>}


    The multiplier defaults to 1, but can be 10 or 100. The SI-prefix-integer are specific integers for which an SI prefix is defined (-24, -21, ...-6, -3, -2, -1, 0, 1, 2, 3, 6, ...21, 24). If the provided integer is not in this list, a ?? is output. If the integer is in the list, the appropriate SI-prefix is output following the multiplier.



    The macro that feeds prefixSN in the proper syntax is called prefixmult, with syntax



    prefixmult{1E<integer>}


    Here integer should be in the range -24 to 26. Based on the value of the integer, it sets the prefix as 1, 10, or 100, and adjusts the integer to the next lower SI standard value. For example if the input to prefixmult was 1E5, it would set the call prefixSI[100]{1E3}.



    The top-level macro, prefix, which feeds prefixmult its integer format, can take input in four possible form s:



    prefix{1E<integer>}
    prefix{1e<integer>}
    prefix{10<...>0}
    prefix{.0<...>01}


    It sorts through looking for an E or e. Finding one, it passes the capital-E form to prefixmult with the associated integer. If no E is found, it looks for a decimal point, a 1 and multiple 0 tokens. Based on what it finds, it reconstructs the associated integer based on the number of zeros and passes it onto prefixmult.



    Here is the MWE.



    documentclass{article}
    usepackage{siunitx,listofitems}
    newcommandprefixSN[2][1]{#1,prefixSNaux#2relax}
    defprefixSNaux 1E#1relax{%
    ifnum#1=0relaxelse
    ifnum#1=-1relaxtextrm{d}else
    ifnum#1=-2relaxtextrm{c}else
    ifnum#1=-3relaxtextrm{m}else
    ifnum#1=-6relaxtextrm{ensuremath{mu}}else
    ifnum#1=-9relaxtextrm{n}else
    ifnum#1=-12relaxtextrm{p}else
    ifnum#1=-15relaxtextrm{f}else
    ifnum#1=-18relaxtextrm{a}else
    ifnum#1=-21relaxtextrm{z}else
    ifnum#1=-24relaxtextrm{y}else
    ifnum#1=1relaxtextrm{da}else
    ifnum#1=2relaxtextrm{h}else
    ifnum#1=3relaxtextrm{k}else
    ifnum#1=6relaxtextrm{M}else
    ifnum#1=9relaxtextrm{G}else
    ifnum#1=12relaxtextrm{T}else
    ifnum#1=15relaxtextrm{P}else
    ifnum#1=18relaxtextrm{E}else
    ifnum#1=21relaxtextrm{Z}else
    ifnum#1=24relaxtextrm{Y}else
    ??%
    fififififififififififififififififififififi
    }
    newcommandprefix[1]{%
    setsepchar{1E||1e}%
    readlistscinot{#1}%
    ifnumscinotlen>1relax
    itemtomacroscinot[2]temp%
    expandafterprefixmultexpandafter{expandafter1expandafter Etemp}%
    else
    setsepchar{./1/0}%
    readlistzerocount{#1}%
    ifnumzerocountlen=1relax
    expandafterprefixmultexpandafter{expandafter1expandafter E%
    thenumexprlistlenzerocount[1,2]-1relax}%
    else
    expandafterprefixmultexpandafter{expandafter1expandafter E%
    expandafter-thenumexprlistlenzerocount[2,1]relax}%
    fi
    fi
    }
    newcommandprefixmult[1]{prefixmultaux#1relax}
    defprefixmultaux 1E#1relax{%
    setsepchar{E4||E7||E10||E13||E16||E19||E22||E25||%
    E-5||E-8||E-11||E-14||E-17||E-20||E-23}%
    readlistfactormult{E#1}%
    ifnumfactormultlen>1relax
    prefixSN[10]{1Ethenumexpr#1-1relax}
    else
    setsepchar{E5||E8||E11||E14||E17||E20||E23||E26||%
    E-4||E-7||E-10||E-13||E-16||E-19||E-22}%
    readlistfactormult{E#1}%
    ifnumfactormultlen>1relax
    prefixSN[100]{1Ethenumexpr#1-2relax}
    else
    prefixSN[1]{1E#1}%
    fi
    fi
    }
    begin{document}
    prefix{1E6}par
    prefix{1E-15}par
    prefix{1e-6}par
    prefix{100}par
    prefix{1000000}par
    prefix{.001}par
    prefix{.000001}par
    prefix{1E5}par
    prefix{10000}par
    prefix{.0001}par
    prefix{1E7}par
    prefix{1E-5}par
    prefix{1E8}par
    prefix{1E-4}
    end{document}


    enter image description here



    SUPPLEMENT



    Not sure if this is an improvement, as it seems to me that the prefix should deal solely in powers of 10. However, if one wished for a more general implementation that could handle any multiplier of a single significant digit, then here it is:



    documentclass{article}
    usepackage{siunitx,listofitems}
    newcommandprefixSN[2][1]{#1,prefixSNaux#2relax}
    defprefixSNaux 1E#1relax{%
    ifnum#1=0relaxelse
    ifnum#1=-1relaxtextrm{d}else
    ifnum#1=-2relaxtextrm{c}else
    ifnum#1=-3relaxtextrm{m}else
    ifnum#1=-6relaxtextrm{ensuremath{mu}}else
    ifnum#1=-9relaxtextrm{n}else
    ifnum#1=-12relaxtextrm{p}else
    ifnum#1=-15relaxtextrm{f}else
    ifnum#1=-18relaxtextrm{a}else
    ifnum#1=-21relaxtextrm{z}else
    ifnum#1=-24relaxtextrm{y}else
    ifnum#1=1relaxtextrm{da}else
    ifnum#1=2relaxtextrm{h}else
    ifnum#1=3relaxtextrm{k}else
    ifnum#1=6relaxtextrm{M}else
    ifnum#1=9relaxtextrm{G}else
    ifnum#1=12relaxtextrm{T}else
    ifnum#1=15relaxtextrm{P}else
    ifnum#1=18relaxtextrm{E}else
    ifnum#1=21relaxtextrm{Z}else
    ifnum#1=24relaxtextrm{Y}else
    ??%
    fififififififififififififififififififififi
    }
    newcommandprefix[1]{%
    setsepchar{E||e}%
    readlistscinot{#1}%
    ifnumscinotlen>1relax
    itemtomacroscinot[1]premult%
    itemtomacroscinot[2]temp%
    expandafterexpandafterexpandafterprefixmult
    expandafterexpandafterexpandafter{%
    expandafterpremultexpandafter Etemp}%
    else
    setsepchar{./1||2||3||4||5||6||7||8||9/0}%
    readlistzerocount{#1}%
    ifnumzerocountlen=1relax
    expandafterexpandafterexpandafterdef
    expandafterexpandafterexpandaftertemp
    expandafterexpandafterexpandafter{zerocountsep[1,1]}%
    expandafterexpandafterexpandafterprefixmult
    expandafterexpandafterexpandafter{%
    expandaftertempexpandafter E%
    thenumexprlistlenzerocount[1,2]-1relax}%
    else
    expandafterexpandafterexpandafterdef
    expandafterexpandafterexpandaftertemp
    expandafterexpandafterexpandafter{zerocountsep[2,1]}%
    expandafterexpandafterexpandafterprefixmult
    expandafterexpandafterexpandafter{%
    expandaftertempexpandafter E%
    expandafter-thenumexprlistlenzerocount[2,1]relax}%
    fi
    fi
    }
    newcommandprefixmult[1]{prefixmultaux#1relax}
    defprefixmultaux #1E#2relax{%
    setsepchar{E4||E7||E10||E13||E16||E19||E22||E25||%
    E-5||E-8||E-11||E-14||E-17||E-20||E-23}%
    readlistfactormult{E#2}%
    ifnumfactormultlen>1relax
    prefixSN[#10]{1Ethenumexpr#2-1relax}
    else
    setsepchar{E5||E8||E11||E14||E17||E20||E23||E26||%
    E-4||E-7||E-10||E-13||E-16||E-19||E-22}%
    readlistfactormult{E#2}%
    ifnumfactormultlen>1relax
    prefixSN[#100]{1Ethenumexpr#2-2relax}
    else
    prefixSN[#1]{1E#2}%
    fi
    fi
    }
    begin{document}
    prefix{4E6}par
    prefix{1E-15}par
    prefix{1e-6}par
    prefix{300}par
    prefix{1000000}par
    prefix{.001}par
    prefix{.000004}par
    prefix{1E5}par
    prefix{10000}par
    prefix{.0001}par
    prefix{5E7}par
    prefix{1E-5}par
    prefix{3E8}par
    prefix{1E-4}
    end{document}


    enter image description here






    share|improve this answer















    EDITED to solve both input forms. EDITED so that either capital or lowercase E is permitted in the scientific notation (e.g., 1E6 or 1e6).



    EDITED to automatically discern multipliers of 1, 10 or 100 on standard units.



    If the prefix is outside the range of 1E-24 to 1E26, a ?? is output.



    See SUPPLEMENT for more general use of multipliers (outside of 1, 10, 100).



    As this answer has expanded with EDITS, let me explan the logic. There are 3 macros that call each other in sequence. Let me work my way from the end to the beginning. The lowest level macro is



    prefixSN[<multiplier>]{1E<SI-prefix-integer>}


    The multiplier defaults to 1, but can be 10 or 100. The SI-prefix-integer are specific integers for which an SI prefix is defined (-24, -21, ...-6, -3, -2, -1, 0, 1, 2, 3, 6, ...21, 24). If the provided integer is not in this list, a ?? is output. If the integer is in the list, the appropriate SI-prefix is output following the multiplier.



    The macro that feeds prefixSN in the proper syntax is called prefixmult, with syntax



    prefixmult{1E<integer>}


    Here integer should be in the range -24 to 26. Based on the value of the integer, it sets the prefix as 1, 10, or 100, and adjusts the integer to the next lower SI standard value. For example if the input to prefixmult was 1E5, it would set the call prefixSI[100]{1E3}.



    The top-level macro, prefix, which feeds prefixmult its integer format, can take input in four possible form s:



    prefix{1E<integer>}
    prefix{1e<integer>}
    prefix{10<...>0}
    prefix{.0<...>01}


    It sorts through looking for an E or e. Finding one, it passes the capital-E form to prefixmult with the associated integer. If no E is found, it looks for a decimal point, a 1 and multiple 0 tokens. Based on what it finds, it reconstructs the associated integer based on the number of zeros and passes it onto prefixmult.



    Here is the MWE.



    documentclass{article}
    usepackage{siunitx,listofitems}
    newcommandprefixSN[2][1]{#1,prefixSNaux#2relax}
    defprefixSNaux 1E#1relax{%
    ifnum#1=0relaxelse
    ifnum#1=-1relaxtextrm{d}else
    ifnum#1=-2relaxtextrm{c}else
    ifnum#1=-3relaxtextrm{m}else
    ifnum#1=-6relaxtextrm{ensuremath{mu}}else
    ifnum#1=-9relaxtextrm{n}else
    ifnum#1=-12relaxtextrm{p}else
    ifnum#1=-15relaxtextrm{f}else
    ifnum#1=-18relaxtextrm{a}else
    ifnum#1=-21relaxtextrm{z}else
    ifnum#1=-24relaxtextrm{y}else
    ifnum#1=1relaxtextrm{da}else
    ifnum#1=2relaxtextrm{h}else
    ifnum#1=3relaxtextrm{k}else
    ifnum#1=6relaxtextrm{M}else
    ifnum#1=9relaxtextrm{G}else
    ifnum#1=12relaxtextrm{T}else
    ifnum#1=15relaxtextrm{P}else
    ifnum#1=18relaxtextrm{E}else
    ifnum#1=21relaxtextrm{Z}else
    ifnum#1=24relaxtextrm{Y}else
    ??%
    fififififififififififififififififififififi
    }
    newcommandprefix[1]{%
    setsepchar{1E||1e}%
    readlistscinot{#1}%
    ifnumscinotlen>1relax
    itemtomacroscinot[2]temp%
    expandafterprefixmultexpandafter{expandafter1expandafter Etemp}%
    else
    setsepchar{./1/0}%
    readlistzerocount{#1}%
    ifnumzerocountlen=1relax
    expandafterprefixmultexpandafter{expandafter1expandafter E%
    thenumexprlistlenzerocount[1,2]-1relax}%
    else
    expandafterprefixmultexpandafter{expandafter1expandafter E%
    expandafter-thenumexprlistlenzerocount[2,1]relax}%
    fi
    fi
    }
    newcommandprefixmult[1]{prefixmultaux#1relax}
    defprefixmultaux 1E#1relax{%
    setsepchar{E4||E7||E10||E13||E16||E19||E22||E25||%
    E-5||E-8||E-11||E-14||E-17||E-20||E-23}%
    readlistfactormult{E#1}%
    ifnumfactormultlen>1relax
    prefixSN[10]{1Ethenumexpr#1-1relax}
    else
    setsepchar{E5||E8||E11||E14||E17||E20||E23||E26||%
    E-4||E-7||E-10||E-13||E-16||E-19||E-22}%
    readlistfactormult{E#1}%
    ifnumfactormultlen>1relax
    prefixSN[100]{1Ethenumexpr#1-2relax}
    else
    prefixSN[1]{1E#1}%
    fi
    fi
    }
    begin{document}
    prefix{1E6}par
    prefix{1E-15}par
    prefix{1e-6}par
    prefix{100}par
    prefix{1000000}par
    prefix{.001}par
    prefix{.000001}par
    prefix{1E5}par
    prefix{10000}par
    prefix{.0001}par
    prefix{1E7}par
    prefix{1E-5}par
    prefix{1E8}par
    prefix{1E-4}
    end{document}


    enter image description here



    SUPPLEMENT



    Not sure if this is an improvement, as it seems to me that the prefix should deal solely in powers of 10. However, if one wished for a more general implementation that could handle any multiplier of a single significant digit, then here it is:



    documentclass{article}
    usepackage{siunitx,listofitems}
    newcommandprefixSN[2][1]{#1,prefixSNaux#2relax}
    defprefixSNaux 1E#1relax{%
    ifnum#1=0relaxelse
    ifnum#1=-1relaxtextrm{d}else
    ifnum#1=-2relaxtextrm{c}else
    ifnum#1=-3relaxtextrm{m}else
    ifnum#1=-6relaxtextrm{ensuremath{mu}}else
    ifnum#1=-9relaxtextrm{n}else
    ifnum#1=-12relaxtextrm{p}else
    ifnum#1=-15relaxtextrm{f}else
    ifnum#1=-18relaxtextrm{a}else
    ifnum#1=-21relaxtextrm{z}else
    ifnum#1=-24relaxtextrm{y}else
    ifnum#1=1relaxtextrm{da}else
    ifnum#1=2relaxtextrm{h}else
    ifnum#1=3relaxtextrm{k}else
    ifnum#1=6relaxtextrm{M}else
    ifnum#1=9relaxtextrm{G}else
    ifnum#1=12relaxtextrm{T}else
    ifnum#1=15relaxtextrm{P}else
    ifnum#1=18relaxtextrm{E}else
    ifnum#1=21relaxtextrm{Z}else
    ifnum#1=24relaxtextrm{Y}else
    ??%
    fififififififififififififififififififififi
    }
    newcommandprefix[1]{%
    setsepchar{E||e}%
    readlistscinot{#1}%
    ifnumscinotlen>1relax
    itemtomacroscinot[1]premult%
    itemtomacroscinot[2]temp%
    expandafterexpandafterexpandafterprefixmult
    expandafterexpandafterexpandafter{%
    expandafterpremultexpandafter Etemp}%
    else
    setsepchar{./1||2||3||4||5||6||7||8||9/0}%
    readlistzerocount{#1}%
    ifnumzerocountlen=1relax
    expandafterexpandafterexpandafterdef
    expandafterexpandafterexpandaftertemp
    expandafterexpandafterexpandafter{zerocountsep[1,1]}%
    expandafterexpandafterexpandafterprefixmult
    expandafterexpandafterexpandafter{%
    expandaftertempexpandafter E%
    thenumexprlistlenzerocount[1,2]-1relax}%
    else
    expandafterexpandafterexpandafterdef
    expandafterexpandafterexpandaftertemp
    expandafterexpandafterexpandafter{zerocountsep[2,1]}%
    expandafterexpandafterexpandafterprefixmult
    expandafterexpandafterexpandafter{%
    expandaftertempexpandafter E%
    expandafter-thenumexprlistlenzerocount[2,1]relax}%
    fi
    fi
    }
    newcommandprefixmult[1]{prefixmultaux#1relax}
    defprefixmultaux #1E#2relax{%
    setsepchar{E4||E7||E10||E13||E16||E19||E22||E25||%
    E-5||E-8||E-11||E-14||E-17||E-20||E-23}%
    readlistfactormult{E#2}%
    ifnumfactormultlen>1relax
    prefixSN[#10]{1Ethenumexpr#2-1relax}
    else
    setsepchar{E5||E8||E11||E14||E17||E20||E23||E26||%
    E-4||E-7||E-10||E-13||E-16||E-19||E-22}%
    readlistfactormult{E#2}%
    ifnumfactormultlen>1relax
    prefixSN[#100]{1Ethenumexpr#2-2relax}
    else
    prefixSN[#1]{1E#2}%
    fi
    fi
    }
    begin{document}
    prefix{4E6}par
    prefix{1E-15}par
    prefix{1e-6}par
    prefix{300}par
    prefix{1000000}par
    prefix{.001}par
    prefix{.000004}par
    prefix{1E5}par
    prefix{10000}par
    prefix{.0001}par
    prefix{5E7}par
    prefix{1E-5}par
    prefix{3E8}par
    prefix{1E-4}
    end{document}


    enter image description here







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 8 hours ago

























    answered 10 hours ago









    Steven B. SegletesSteven B. Segletes

    167k9 gold badges210 silver badges428 bronze badges




    167k9 gold badges210 silver badges428 bronze badges













    • Awesome! Now all that remains is for someone to figure out how to convert prefix{10000} to 10k =)

      – N3buchadnezzar
      10 hours ago






    • 1





      @N3buchadnezzar Ask and ye shall receive. Done.

      – Steven B. Segletes
      9 hours ago



















    • Awesome! Now all that remains is for someone to figure out how to convert prefix{10000} to 10k =)

      – N3buchadnezzar
      10 hours ago






    • 1





      @N3buchadnezzar Ask and ye shall receive. Done.

      – Steven B. Segletes
      9 hours ago

















    Awesome! Now all that remains is for someone to figure out how to convert prefix{10000} to 10k =)

    – N3buchadnezzar
    10 hours ago





    Awesome! Now all that remains is for someone to figure out how to convert prefix{10000} to 10k =)

    – N3buchadnezzar
    10 hours ago




    1




    1





    @N3buchadnezzar Ask and ye shall receive. Done.

    – Steven B. Segletes
    9 hours ago





    @N3buchadnezzar Ask and ye shall receive. Done.

    – Steven B. Segletes
    9 hours ago













    2














    This supports both exponential and standard notation.



    No check about the nonzero digit is performed, the input is assumed to be of the form



    1<sequence of zeros>
    -1<sequence of zeros>
    1e<exponent>
    1E<exponent>
    -1e<exponent>
    -1E<exponent>


    The range is -1E-26 to 1E26. Numbers outside this range silently fail. You can add control about the range.



    Here's the code: note that the bulk of the work is performed by __nebuch_prefix_exp:nn (precisely by the :ee variant).



    documentclass{article}
    usepackage{siunitx} % also loads xparse and expl3

    ExplSyntaxOn
    NewDocumentCommand{prefix}{m}
    {
    nebuch_prefix:e { tl_lower_case:n { #1 } }
    }

    seq_new:N l__nebuch_prefix_input_seq

    cs_new_protected:Nn nebuch_prefix:n
    {
    seq_set_split:Nnn l__nebuch_prefix_input_seq { e } { #1 }
    int_compare:nTF { seq_count:N l__nebuch_prefix_input_seq > 1 }
    {% there was e/E
    __nebuch_prefix_exp:ee
    { seq_item:Nn l__nebuch_prefix_input_seq { 1 } }
    { seq_item:Nn l__nebuch_prefix_input_seq { 2 } }
    }
    {% no e/E
    __nebuch_prefix_long:n { #1 }
    }
    }
    cs_generate_variant:Nn nebuch_prefix:n { e }

    cs_new_protected:Nn __nebuch_prefix_exp:nn
    {
    int_compare:nTF { int_mod:nn { #2 } { 3 } < 0 }
    {
    __nebuch_prefix_exp:ee
    { #1 prg_replicate:nn { 3 + int_mod:nn { #2 } { 3 } } { 0 } }
    { int_eval:n { #2 - 3 - int_mod:nn { #2 } { 3 } } }
    }
    {
    SI
    {
    #1 % 1 or -1
    prg_replicate:nn { int_mod:nn { #2 } { 3 } } { 0 }
    }
    {
    int_case:nn { int_div_truncate:nn { #2 } { 3 } }
    {
    {-8}{yoctovoidunit}
    {-7}{zeptovoidunit}
    {-6}{attovoidunit}
    {-5}{femtovoidunit}
    {-4}{picovoidunit}
    {-3}{nanovoidunit}
    {-2}{microvoidunit}
    {-1}{millivoidunit}
    {0}{!voidunit}
    {1}{kilovoidunit}
    {2}{megavoidunit}
    {3}{gigavoidunit}
    {4}{teravoidunit}
    {5}{petavoidunit}
    {6}{exavoidunit}
    {7}{zettavoidunit}
    {8}{yottavoidunit}
    }
    }
    }
    }
    cs_generate_variant:Nn __nebuch_prefix_exp:nn {ee}

    cs_new_protected:Nn __nebuch_prefix_long:n
    {
    % count the number of zeros
    regex_split:nnN { (-*1+) } { #1 } l__nebuch_prefix_input_seq
    __nebuch_prefix_exp:ee
    { seq_item:Nn l__nebuch_prefix_input_seq { 2 } }
    { tl_count:e { seq_item:Nn l__nebuch_prefix_input_seq { 3 } } }
    }
    cs_generate_variant:Nn tl_count:n { e }
    ExplSyntaxOff

    DeclareSIUnit{voidunit}{relax}

    begin{document}

    prefix{1e0}

    prefix{1e2}

    prefix{1E4}

    prefix{-1E20}

    prefix{1}

    prefix{10}

    prefix{100}

    prefix{1000}

    prefix{10000}

    prefix{100000}

    prefix{1000000}

    prefix{10000000}

    prefix{100000000}

    prefix{1000000000}

    prefix{-10000000000}

    prefix{100000000000}

    prefix{1E6}

    prefix{1E24}

    prefix{-1E-6}

    prefix{1E-8}

    prefix{-1E-7}

    end{document}


    enter image description here






    share|improve this answer




























      2














      This supports both exponential and standard notation.



      No check about the nonzero digit is performed, the input is assumed to be of the form



      1<sequence of zeros>
      -1<sequence of zeros>
      1e<exponent>
      1E<exponent>
      -1e<exponent>
      -1E<exponent>


      The range is -1E-26 to 1E26. Numbers outside this range silently fail. You can add control about the range.



      Here's the code: note that the bulk of the work is performed by __nebuch_prefix_exp:nn (precisely by the :ee variant).



      documentclass{article}
      usepackage{siunitx} % also loads xparse and expl3

      ExplSyntaxOn
      NewDocumentCommand{prefix}{m}
      {
      nebuch_prefix:e { tl_lower_case:n { #1 } }
      }

      seq_new:N l__nebuch_prefix_input_seq

      cs_new_protected:Nn nebuch_prefix:n
      {
      seq_set_split:Nnn l__nebuch_prefix_input_seq { e } { #1 }
      int_compare:nTF { seq_count:N l__nebuch_prefix_input_seq > 1 }
      {% there was e/E
      __nebuch_prefix_exp:ee
      { seq_item:Nn l__nebuch_prefix_input_seq { 1 } }
      { seq_item:Nn l__nebuch_prefix_input_seq { 2 } }
      }
      {% no e/E
      __nebuch_prefix_long:n { #1 }
      }
      }
      cs_generate_variant:Nn nebuch_prefix:n { e }

      cs_new_protected:Nn __nebuch_prefix_exp:nn
      {
      int_compare:nTF { int_mod:nn { #2 } { 3 } < 0 }
      {
      __nebuch_prefix_exp:ee
      { #1 prg_replicate:nn { 3 + int_mod:nn { #2 } { 3 } } { 0 } }
      { int_eval:n { #2 - 3 - int_mod:nn { #2 } { 3 } } }
      }
      {
      SI
      {
      #1 % 1 or -1
      prg_replicate:nn { int_mod:nn { #2 } { 3 } } { 0 }
      }
      {
      int_case:nn { int_div_truncate:nn { #2 } { 3 } }
      {
      {-8}{yoctovoidunit}
      {-7}{zeptovoidunit}
      {-6}{attovoidunit}
      {-5}{femtovoidunit}
      {-4}{picovoidunit}
      {-3}{nanovoidunit}
      {-2}{microvoidunit}
      {-1}{millivoidunit}
      {0}{!voidunit}
      {1}{kilovoidunit}
      {2}{megavoidunit}
      {3}{gigavoidunit}
      {4}{teravoidunit}
      {5}{petavoidunit}
      {6}{exavoidunit}
      {7}{zettavoidunit}
      {8}{yottavoidunit}
      }
      }
      }
      }
      cs_generate_variant:Nn __nebuch_prefix_exp:nn {ee}

      cs_new_protected:Nn __nebuch_prefix_long:n
      {
      % count the number of zeros
      regex_split:nnN { (-*1+) } { #1 } l__nebuch_prefix_input_seq
      __nebuch_prefix_exp:ee
      { seq_item:Nn l__nebuch_prefix_input_seq { 2 } }
      { tl_count:e { seq_item:Nn l__nebuch_prefix_input_seq { 3 } } }
      }
      cs_generate_variant:Nn tl_count:n { e }
      ExplSyntaxOff

      DeclareSIUnit{voidunit}{relax}

      begin{document}

      prefix{1e0}

      prefix{1e2}

      prefix{1E4}

      prefix{-1E20}

      prefix{1}

      prefix{10}

      prefix{100}

      prefix{1000}

      prefix{10000}

      prefix{100000}

      prefix{1000000}

      prefix{10000000}

      prefix{100000000}

      prefix{1000000000}

      prefix{-10000000000}

      prefix{100000000000}

      prefix{1E6}

      prefix{1E24}

      prefix{-1E-6}

      prefix{1E-8}

      prefix{-1E-7}

      end{document}


      enter image description here






      share|improve this answer


























        2












        2








        2







        This supports both exponential and standard notation.



        No check about the nonzero digit is performed, the input is assumed to be of the form



        1<sequence of zeros>
        -1<sequence of zeros>
        1e<exponent>
        1E<exponent>
        -1e<exponent>
        -1E<exponent>


        The range is -1E-26 to 1E26. Numbers outside this range silently fail. You can add control about the range.



        Here's the code: note that the bulk of the work is performed by __nebuch_prefix_exp:nn (precisely by the :ee variant).



        documentclass{article}
        usepackage{siunitx} % also loads xparse and expl3

        ExplSyntaxOn
        NewDocumentCommand{prefix}{m}
        {
        nebuch_prefix:e { tl_lower_case:n { #1 } }
        }

        seq_new:N l__nebuch_prefix_input_seq

        cs_new_protected:Nn nebuch_prefix:n
        {
        seq_set_split:Nnn l__nebuch_prefix_input_seq { e } { #1 }
        int_compare:nTF { seq_count:N l__nebuch_prefix_input_seq > 1 }
        {% there was e/E
        __nebuch_prefix_exp:ee
        { seq_item:Nn l__nebuch_prefix_input_seq { 1 } }
        { seq_item:Nn l__nebuch_prefix_input_seq { 2 } }
        }
        {% no e/E
        __nebuch_prefix_long:n { #1 }
        }
        }
        cs_generate_variant:Nn nebuch_prefix:n { e }

        cs_new_protected:Nn __nebuch_prefix_exp:nn
        {
        int_compare:nTF { int_mod:nn { #2 } { 3 } < 0 }
        {
        __nebuch_prefix_exp:ee
        { #1 prg_replicate:nn { 3 + int_mod:nn { #2 } { 3 } } { 0 } }
        { int_eval:n { #2 - 3 - int_mod:nn { #2 } { 3 } } }
        }
        {
        SI
        {
        #1 % 1 or -1
        prg_replicate:nn { int_mod:nn { #2 } { 3 } } { 0 }
        }
        {
        int_case:nn { int_div_truncate:nn { #2 } { 3 } }
        {
        {-8}{yoctovoidunit}
        {-7}{zeptovoidunit}
        {-6}{attovoidunit}
        {-5}{femtovoidunit}
        {-4}{picovoidunit}
        {-3}{nanovoidunit}
        {-2}{microvoidunit}
        {-1}{millivoidunit}
        {0}{!voidunit}
        {1}{kilovoidunit}
        {2}{megavoidunit}
        {3}{gigavoidunit}
        {4}{teravoidunit}
        {5}{petavoidunit}
        {6}{exavoidunit}
        {7}{zettavoidunit}
        {8}{yottavoidunit}
        }
        }
        }
        }
        cs_generate_variant:Nn __nebuch_prefix_exp:nn {ee}

        cs_new_protected:Nn __nebuch_prefix_long:n
        {
        % count the number of zeros
        regex_split:nnN { (-*1+) } { #1 } l__nebuch_prefix_input_seq
        __nebuch_prefix_exp:ee
        { seq_item:Nn l__nebuch_prefix_input_seq { 2 } }
        { tl_count:e { seq_item:Nn l__nebuch_prefix_input_seq { 3 } } }
        }
        cs_generate_variant:Nn tl_count:n { e }
        ExplSyntaxOff

        DeclareSIUnit{voidunit}{relax}

        begin{document}

        prefix{1e0}

        prefix{1e2}

        prefix{1E4}

        prefix{-1E20}

        prefix{1}

        prefix{10}

        prefix{100}

        prefix{1000}

        prefix{10000}

        prefix{100000}

        prefix{1000000}

        prefix{10000000}

        prefix{100000000}

        prefix{1000000000}

        prefix{-10000000000}

        prefix{100000000000}

        prefix{1E6}

        prefix{1E24}

        prefix{-1E-6}

        prefix{1E-8}

        prefix{-1E-7}

        end{document}


        enter image description here






        share|improve this answer













        This supports both exponential and standard notation.



        No check about the nonzero digit is performed, the input is assumed to be of the form



        1<sequence of zeros>
        -1<sequence of zeros>
        1e<exponent>
        1E<exponent>
        -1e<exponent>
        -1E<exponent>


        The range is -1E-26 to 1E26. Numbers outside this range silently fail. You can add control about the range.



        Here's the code: note that the bulk of the work is performed by __nebuch_prefix_exp:nn (precisely by the :ee variant).



        documentclass{article}
        usepackage{siunitx} % also loads xparse and expl3

        ExplSyntaxOn
        NewDocumentCommand{prefix}{m}
        {
        nebuch_prefix:e { tl_lower_case:n { #1 } }
        }

        seq_new:N l__nebuch_prefix_input_seq

        cs_new_protected:Nn nebuch_prefix:n
        {
        seq_set_split:Nnn l__nebuch_prefix_input_seq { e } { #1 }
        int_compare:nTF { seq_count:N l__nebuch_prefix_input_seq > 1 }
        {% there was e/E
        __nebuch_prefix_exp:ee
        { seq_item:Nn l__nebuch_prefix_input_seq { 1 } }
        { seq_item:Nn l__nebuch_prefix_input_seq { 2 } }
        }
        {% no e/E
        __nebuch_prefix_long:n { #1 }
        }
        }
        cs_generate_variant:Nn nebuch_prefix:n { e }

        cs_new_protected:Nn __nebuch_prefix_exp:nn
        {
        int_compare:nTF { int_mod:nn { #2 } { 3 } < 0 }
        {
        __nebuch_prefix_exp:ee
        { #1 prg_replicate:nn { 3 + int_mod:nn { #2 } { 3 } } { 0 } }
        { int_eval:n { #2 - 3 - int_mod:nn { #2 } { 3 } } }
        }
        {
        SI
        {
        #1 % 1 or -1
        prg_replicate:nn { int_mod:nn { #2 } { 3 } } { 0 }
        }
        {
        int_case:nn { int_div_truncate:nn { #2 } { 3 } }
        {
        {-8}{yoctovoidunit}
        {-7}{zeptovoidunit}
        {-6}{attovoidunit}
        {-5}{femtovoidunit}
        {-4}{picovoidunit}
        {-3}{nanovoidunit}
        {-2}{microvoidunit}
        {-1}{millivoidunit}
        {0}{!voidunit}
        {1}{kilovoidunit}
        {2}{megavoidunit}
        {3}{gigavoidunit}
        {4}{teravoidunit}
        {5}{petavoidunit}
        {6}{exavoidunit}
        {7}{zettavoidunit}
        {8}{yottavoidunit}
        }
        }
        }
        }
        cs_generate_variant:Nn __nebuch_prefix_exp:nn {ee}

        cs_new_protected:Nn __nebuch_prefix_long:n
        {
        % count the number of zeros
        regex_split:nnN { (-*1+) } { #1 } l__nebuch_prefix_input_seq
        __nebuch_prefix_exp:ee
        { seq_item:Nn l__nebuch_prefix_input_seq { 2 } }
        { tl_count:e { seq_item:Nn l__nebuch_prefix_input_seq { 3 } } }
        }
        cs_generate_variant:Nn tl_count:n { e }
        ExplSyntaxOff

        DeclareSIUnit{voidunit}{relax}

        begin{document}

        prefix{1e0}

        prefix{1e2}

        prefix{1E4}

        prefix{-1E20}

        prefix{1}

        prefix{10}

        prefix{100}

        prefix{1000}

        prefix{10000}

        prefix{100000}

        prefix{1000000}

        prefix{10000000}

        prefix{100000000}

        prefix{1000000000}

        prefix{-10000000000}

        prefix{100000000000}

        prefix{1E6}

        prefix{1E24}

        prefix{-1E-6}

        prefix{1E-8}

        prefix{-1E-7}

        end{document}


        enter image description here







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 7 hours ago









        egregegreg

        750k89 gold badges1964 silver badges3307 bronze badges




        750k89 gold badges1964 silver badges3307 bronze badges























            1














            This allows any (valid, of course) value or expression to be input. The code (ab)uses the LaTeX3 floating point unit to parse the input expression and convert it to exponential notation. With that the code just looks for the correct prefix to apply to that number. Numbers outside the range are printed with more digits to make the number fit the nearest prefix (i.e., 1E28 prints 10000 Y and 1E-28 prints 0.0001 y).



            The prefix macro (which should probably be called postfix :-) is expandable, takes one argument, the number, and prints the it followed by the prefix.



            The prefixSI macro is not expandable and has the same signature as siunitx's SI macro. prefixSI evaluates its first mandatory argument with prefix (nebu_prefix:n, actually), as described above, and passes it to SI. The selected prefix is stored in prefix (inside a group, so that the macro prefix can be used agian) which can be used in an unit expression, for example prefixSI{1000}{prefixmetre} prints 1 km.



            Prefixes can be declared with setprefix <siunitx prefix macro> { <prefix> } { <value> }, like setprefix centi { c } { -2 }. Make sure that the <siunitx prefix macro> exists. If you're not going to use prefixSI then you can use relax there.



            documentclass{article}
            usepackage{siunitx}
            ExplSyntaxOn
            % Internals
            int_new:N l__nebu_min_prefix_int
            tl_new:N l__nebu_base_number_tl
            tl_new:N l__nebu_mode_tl
            cs_new:Npn nebu_prefix:n #1
            {
            exp_args:Nf __nebu_prefix:n
            { exp_args:Nf fp_to_scientific:n { tl_lower_case:n {#1} } }
            }
            cs_new:Npn __nebu_prefix:n #1
            { __nebu_prefix:nwnw #1 q_stop }
            cs_new:Npn __nebu_prefix:nwnw #1 e #2 q_stop
            { __nebu_find_prefix:nnn {#2} {#1} {1} }
            cs_new:Npn __nebu_find_prefix:nnn #1 #2 #3
            {
            tl_if_exist:cT { l__nebu_ #1 tl_use:N l__nebu_mode_tl _prefix_tl }
            {
            use_i_delimit_by_q_stop:nw
            { __nebu_output:nnn {#2} {#1} {#3} }
            }
            int_compare:nNnT {#1} < l__nebu_min_prefix_int
            {
            use_i_delimit_by_q_stop:nw
            {
            exp_args:Nf __nebu_find_prefix:nnn
            { int_eval:n {#1+1} } {#2} {#3/10}
            }
            }
            use_i:nn
            {
            exp_args:Nf __nebu_find_prefix:nnn
            { int_eval:n {#1-1} } {#2} {#3*10}
            }
            q_stop
            }
            exp_args_generate:n { fv }
            cs_new:Npn __nebu_output:nnn #1 #2 #3
            {
            exp_args:Nfv nebu_output:nn
            { fp_to_decimal:n {#1*#3} } { l__nebu_ #2 tl_use:N l__nebu_mode_tl _prefix_tl }
            }
            cs_new_protected:Npn nebu_prefix_set:Nnn #1 #2 #3
            {
            exp_args:Nxx __nebu_prefix_set:nnN
            { tl_trim_spaces:n {#2} } { int_eval:n {#3} } #1
            }
            cs_new_protected:Npn __nebu_prefix_set:nnN #1 #2 #3
            {
            tl_clear_new:c { l__nebu_ #2 _prefix_tl }
            tl_clear_new:c { l__nebu_ #2 _siunitx_prefix_tl }
            tl_set:cn { l__nebu_ #2 _prefix_tl } {#1}
            tl_set:cn { l__nebu_ #2 _siunitx_prefix_tl } {#3}
            int_set:Nn l__nebu_min_prefix_int { int_min:nn {#2} { l__nebu_min_prefix_int } }
            }
            % User interface
            NewExpandableDocumentCommand prefix { m }
            { nebu_prefix:n {#1} }
            cs_new:Npn nebu_output:nn #1 #2 { #1, textrm{#2} }
            NewDocumentCommand setprefix { m m m }
            { nebu_prefix_set:Nnn #1 {#2} {#3} }
            DeclareSIPrefix none { } { 0 }
            setprefix none { } { 0 }
            %
            cs_new_protected:Npn __nebu_store:nn #1 #2
            {
            tl_set:Nn l__nebu_base_number_tl {#1}
            cs_set:Npn prefix {#2}
            }
            NewExpandableDocumentCommand prefixSI { o m o m }
            {
            group_begin:
            cs_set_eq:NN nebu_output:nn __nebu_store:nn
            tl_set:Nn l__nebu_mode_tl { _siunitx }
            nebu_prefix:n {#2}
            SI [#1] { l__nebu_base_number_tl } [#3] {#4}
            group_end:
            }
            ExplSyntaxOff

            setprefix yocto { y } { -24 }
            setprefix zepto { z } { -21 }
            setprefix atto { a } { -18 }
            setprefix femto { f } { -15 }
            setprefix pico { p } { -12 }
            setprefix nano { n } { -9 }
            setprefix micro { SIUnitSymbolMicro } { -6 }
            setprefix milli { m } { -3 }
            setprefix centi { c } { -2 }
            setprefix deci { d } { -1 }
            setprefix deca { da } { 1 }
            setprefix hecto { h } { 2 }
            setprefix kilo { k } { 3 }
            setprefix mega { M } { 6 }
            setprefix giga { G } { 9 }
            setprefix tera { T } { 12 }
            setprefix peta { P } { 15 }
            setprefix exa { E } { 18 }
            setprefix zetta { Z } { 21 }
            setprefix yotta { Y } { 24 }

            begin{document}
            prefix{1}par
            prefix{4E6}par
            prefix{1E-15}par
            prefix{1e-6}par
            prefix{300}par
            prefix{1000000}par
            prefix{.001}par
            prefix{.000004}par
            prefix{1E5}par
            prefix{10000}par
            prefix{.0001}par
            prefix{5E7}par
            prefix{1E-5}par
            prefix{3E8}par
            prefix{1E-4}par
            prefix{1E-24}par
            prefix{1E-28}par
            prefix{1E24}par
            prefix{1E28}par
            prefix{1e3*pi}par
            prefixSI{1e3*pi}{prefixmetre}par
            end{document}



            enter image description here







            share|improve this answer


























            • How would 10E-4 metres look? ;-) Great answer!

              – N3buchadnezzar
              6 hours ago






            • 1





              @N3buchadnezzar Thanks! A millimetre: 1 mm? Is there something wrong?

              – Phelype Oleinik
              6 hours ago
















            1














            This allows any (valid, of course) value or expression to be input. The code (ab)uses the LaTeX3 floating point unit to parse the input expression and convert it to exponential notation. With that the code just looks for the correct prefix to apply to that number. Numbers outside the range are printed with more digits to make the number fit the nearest prefix (i.e., 1E28 prints 10000 Y and 1E-28 prints 0.0001 y).



            The prefix macro (which should probably be called postfix :-) is expandable, takes one argument, the number, and prints the it followed by the prefix.



            The prefixSI macro is not expandable and has the same signature as siunitx's SI macro. prefixSI evaluates its first mandatory argument with prefix (nebu_prefix:n, actually), as described above, and passes it to SI. The selected prefix is stored in prefix (inside a group, so that the macro prefix can be used agian) which can be used in an unit expression, for example prefixSI{1000}{prefixmetre} prints 1 km.



            Prefixes can be declared with setprefix <siunitx prefix macro> { <prefix> } { <value> }, like setprefix centi { c } { -2 }. Make sure that the <siunitx prefix macro> exists. If you're not going to use prefixSI then you can use relax there.



            documentclass{article}
            usepackage{siunitx}
            ExplSyntaxOn
            % Internals
            int_new:N l__nebu_min_prefix_int
            tl_new:N l__nebu_base_number_tl
            tl_new:N l__nebu_mode_tl
            cs_new:Npn nebu_prefix:n #1
            {
            exp_args:Nf __nebu_prefix:n
            { exp_args:Nf fp_to_scientific:n { tl_lower_case:n {#1} } }
            }
            cs_new:Npn __nebu_prefix:n #1
            { __nebu_prefix:nwnw #1 q_stop }
            cs_new:Npn __nebu_prefix:nwnw #1 e #2 q_stop
            { __nebu_find_prefix:nnn {#2} {#1} {1} }
            cs_new:Npn __nebu_find_prefix:nnn #1 #2 #3
            {
            tl_if_exist:cT { l__nebu_ #1 tl_use:N l__nebu_mode_tl _prefix_tl }
            {
            use_i_delimit_by_q_stop:nw
            { __nebu_output:nnn {#2} {#1} {#3} }
            }
            int_compare:nNnT {#1} < l__nebu_min_prefix_int
            {
            use_i_delimit_by_q_stop:nw
            {
            exp_args:Nf __nebu_find_prefix:nnn
            { int_eval:n {#1+1} } {#2} {#3/10}
            }
            }
            use_i:nn
            {
            exp_args:Nf __nebu_find_prefix:nnn
            { int_eval:n {#1-1} } {#2} {#3*10}
            }
            q_stop
            }
            exp_args_generate:n { fv }
            cs_new:Npn __nebu_output:nnn #1 #2 #3
            {
            exp_args:Nfv nebu_output:nn
            { fp_to_decimal:n {#1*#3} } { l__nebu_ #2 tl_use:N l__nebu_mode_tl _prefix_tl }
            }
            cs_new_protected:Npn nebu_prefix_set:Nnn #1 #2 #3
            {
            exp_args:Nxx __nebu_prefix_set:nnN
            { tl_trim_spaces:n {#2} } { int_eval:n {#3} } #1
            }
            cs_new_protected:Npn __nebu_prefix_set:nnN #1 #2 #3
            {
            tl_clear_new:c { l__nebu_ #2 _prefix_tl }
            tl_clear_new:c { l__nebu_ #2 _siunitx_prefix_tl }
            tl_set:cn { l__nebu_ #2 _prefix_tl } {#1}
            tl_set:cn { l__nebu_ #2 _siunitx_prefix_tl } {#3}
            int_set:Nn l__nebu_min_prefix_int { int_min:nn {#2} { l__nebu_min_prefix_int } }
            }
            % User interface
            NewExpandableDocumentCommand prefix { m }
            { nebu_prefix:n {#1} }
            cs_new:Npn nebu_output:nn #1 #2 { #1, textrm{#2} }
            NewDocumentCommand setprefix { m m m }
            { nebu_prefix_set:Nnn #1 {#2} {#3} }
            DeclareSIPrefix none { } { 0 }
            setprefix none { } { 0 }
            %
            cs_new_protected:Npn __nebu_store:nn #1 #2
            {
            tl_set:Nn l__nebu_base_number_tl {#1}
            cs_set:Npn prefix {#2}
            }
            NewExpandableDocumentCommand prefixSI { o m o m }
            {
            group_begin:
            cs_set_eq:NN nebu_output:nn __nebu_store:nn
            tl_set:Nn l__nebu_mode_tl { _siunitx }
            nebu_prefix:n {#2}
            SI [#1] { l__nebu_base_number_tl } [#3] {#4}
            group_end:
            }
            ExplSyntaxOff

            setprefix yocto { y } { -24 }
            setprefix zepto { z } { -21 }
            setprefix atto { a } { -18 }
            setprefix femto { f } { -15 }
            setprefix pico { p } { -12 }
            setprefix nano { n } { -9 }
            setprefix micro { SIUnitSymbolMicro } { -6 }
            setprefix milli { m } { -3 }
            setprefix centi { c } { -2 }
            setprefix deci { d } { -1 }
            setprefix deca { da } { 1 }
            setprefix hecto { h } { 2 }
            setprefix kilo { k } { 3 }
            setprefix mega { M } { 6 }
            setprefix giga { G } { 9 }
            setprefix tera { T } { 12 }
            setprefix peta { P } { 15 }
            setprefix exa { E } { 18 }
            setprefix zetta { Z } { 21 }
            setprefix yotta { Y } { 24 }

            begin{document}
            prefix{1}par
            prefix{4E6}par
            prefix{1E-15}par
            prefix{1e-6}par
            prefix{300}par
            prefix{1000000}par
            prefix{.001}par
            prefix{.000004}par
            prefix{1E5}par
            prefix{10000}par
            prefix{.0001}par
            prefix{5E7}par
            prefix{1E-5}par
            prefix{3E8}par
            prefix{1E-4}par
            prefix{1E-24}par
            prefix{1E-28}par
            prefix{1E24}par
            prefix{1E28}par
            prefix{1e3*pi}par
            prefixSI{1e3*pi}{prefixmetre}par
            end{document}



            enter image description here







            share|improve this answer


























            • How would 10E-4 metres look? ;-) Great answer!

              – N3buchadnezzar
              6 hours ago






            • 1





              @N3buchadnezzar Thanks! A millimetre: 1 mm? Is there something wrong?

              – Phelype Oleinik
              6 hours ago














            1












            1








            1







            This allows any (valid, of course) value or expression to be input. The code (ab)uses the LaTeX3 floating point unit to parse the input expression and convert it to exponential notation. With that the code just looks for the correct prefix to apply to that number. Numbers outside the range are printed with more digits to make the number fit the nearest prefix (i.e., 1E28 prints 10000 Y and 1E-28 prints 0.0001 y).



            The prefix macro (which should probably be called postfix :-) is expandable, takes one argument, the number, and prints the it followed by the prefix.



            The prefixSI macro is not expandable and has the same signature as siunitx's SI macro. prefixSI evaluates its first mandatory argument with prefix (nebu_prefix:n, actually), as described above, and passes it to SI. The selected prefix is stored in prefix (inside a group, so that the macro prefix can be used agian) which can be used in an unit expression, for example prefixSI{1000}{prefixmetre} prints 1 km.



            Prefixes can be declared with setprefix <siunitx prefix macro> { <prefix> } { <value> }, like setprefix centi { c } { -2 }. Make sure that the <siunitx prefix macro> exists. If you're not going to use prefixSI then you can use relax there.



            documentclass{article}
            usepackage{siunitx}
            ExplSyntaxOn
            % Internals
            int_new:N l__nebu_min_prefix_int
            tl_new:N l__nebu_base_number_tl
            tl_new:N l__nebu_mode_tl
            cs_new:Npn nebu_prefix:n #1
            {
            exp_args:Nf __nebu_prefix:n
            { exp_args:Nf fp_to_scientific:n { tl_lower_case:n {#1} } }
            }
            cs_new:Npn __nebu_prefix:n #1
            { __nebu_prefix:nwnw #1 q_stop }
            cs_new:Npn __nebu_prefix:nwnw #1 e #2 q_stop
            { __nebu_find_prefix:nnn {#2} {#1} {1} }
            cs_new:Npn __nebu_find_prefix:nnn #1 #2 #3
            {
            tl_if_exist:cT { l__nebu_ #1 tl_use:N l__nebu_mode_tl _prefix_tl }
            {
            use_i_delimit_by_q_stop:nw
            { __nebu_output:nnn {#2} {#1} {#3} }
            }
            int_compare:nNnT {#1} < l__nebu_min_prefix_int
            {
            use_i_delimit_by_q_stop:nw
            {
            exp_args:Nf __nebu_find_prefix:nnn
            { int_eval:n {#1+1} } {#2} {#3/10}
            }
            }
            use_i:nn
            {
            exp_args:Nf __nebu_find_prefix:nnn
            { int_eval:n {#1-1} } {#2} {#3*10}
            }
            q_stop
            }
            exp_args_generate:n { fv }
            cs_new:Npn __nebu_output:nnn #1 #2 #3
            {
            exp_args:Nfv nebu_output:nn
            { fp_to_decimal:n {#1*#3} } { l__nebu_ #2 tl_use:N l__nebu_mode_tl _prefix_tl }
            }
            cs_new_protected:Npn nebu_prefix_set:Nnn #1 #2 #3
            {
            exp_args:Nxx __nebu_prefix_set:nnN
            { tl_trim_spaces:n {#2} } { int_eval:n {#3} } #1
            }
            cs_new_protected:Npn __nebu_prefix_set:nnN #1 #2 #3
            {
            tl_clear_new:c { l__nebu_ #2 _prefix_tl }
            tl_clear_new:c { l__nebu_ #2 _siunitx_prefix_tl }
            tl_set:cn { l__nebu_ #2 _prefix_tl } {#1}
            tl_set:cn { l__nebu_ #2 _siunitx_prefix_tl } {#3}
            int_set:Nn l__nebu_min_prefix_int { int_min:nn {#2} { l__nebu_min_prefix_int } }
            }
            % User interface
            NewExpandableDocumentCommand prefix { m }
            { nebu_prefix:n {#1} }
            cs_new:Npn nebu_output:nn #1 #2 { #1, textrm{#2} }
            NewDocumentCommand setprefix { m m m }
            { nebu_prefix_set:Nnn #1 {#2} {#3} }
            DeclareSIPrefix none { } { 0 }
            setprefix none { } { 0 }
            %
            cs_new_protected:Npn __nebu_store:nn #1 #2
            {
            tl_set:Nn l__nebu_base_number_tl {#1}
            cs_set:Npn prefix {#2}
            }
            NewExpandableDocumentCommand prefixSI { o m o m }
            {
            group_begin:
            cs_set_eq:NN nebu_output:nn __nebu_store:nn
            tl_set:Nn l__nebu_mode_tl { _siunitx }
            nebu_prefix:n {#2}
            SI [#1] { l__nebu_base_number_tl } [#3] {#4}
            group_end:
            }
            ExplSyntaxOff

            setprefix yocto { y } { -24 }
            setprefix zepto { z } { -21 }
            setprefix atto { a } { -18 }
            setprefix femto { f } { -15 }
            setprefix pico { p } { -12 }
            setprefix nano { n } { -9 }
            setprefix micro { SIUnitSymbolMicro } { -6 }
            setprefix milli { m } { -3 }
            setprefix centi { c } { -2 }
            setprefix deci { d } { -1 }
            setprefix deca { da } { 1 }
            setprefix hecto { h } { 2 }
            setprefix kilo { k } { 3 }
            setprefix mega { M } { 6 }
            setprefix giga { G } { 9 }
            setprefix tera { T } { 12 }
            setprefix peta { P } { 15 }
            setprefix exa { E } { 18 }
            setprefix zetta { Z } { 21 }
            setprefix yotta { Y } { 24 }

            begin{document}
            prefix{1}par
            prefix{4E6}par
            prefix{1E-15}par
            prefix{1e-6}par
            prefix{300}par
            prefix{1000000}par
            prefix{.001}par
            prefix{.000004}par
            prefix{1E5}par
            prefix{10000}par
            prefix{.0001}par
            prefix{5E7}par
            prefix{1E-5}par
            prefix{3E8}par
            prefix{1E-4}par
            prefix{1E-24}par
            prefix{1E-28}par
            prefix{1E24}par
            prefix{1E28}par
            prefix{1e3*pi}par
            prefixSI{1e3*pi}{prefixmetre}par
            end{document}



            enter image description here







            share|improve this answer















            This allows any (valid, of course) value or expression to be input. The code (ab)uses the LaTeX3 floating point unit to parse the input expression and convert it to exponential notation. With that the code just looks for the correct prefix to apply to that number. Numbers outside the range are printed with more digits to make the number fit the nearest prefix (i.e., 1E28 prints 10000 Y and 1E-28 prints 0.0001 y).



            The prefix macro (which should probably be called postfix :-) is expandable, takes one argument, the number, and prints the it followed by the prefix.



            The prefixSI macro is not expandable and has the same signature as siunitx's SI macro. prefixSI evaluates its first mandatory argument with prefix (nebu_prefix:n, actually), as described above, and passes it to SI. The selected prefix is stored in prefix (inside a group, so that the macro prefix can be used agian) which can be used in an unit expression, for example prefixSI{1000}{prefixmetre} prints 1 km.



            Prefixes can be declared with setprefix <siunitx prefix macro> { <prefix> } { <value> }, like setprefix centi { c } { -2 }. Make sure that the <siunitx prefix macro> exists. If you're not going to use prefixSI then you can use relax there.



            documentclass{article}
            usepackage{siunitx}
            ExplSyntaxOn
            % Internals
            int_new:N l__nebu_min_prefix_int
            tl_new:N l__nebu_base_number_tl
            tl_new:N l__nebu_mode_tl
            cs_new:Npn nebu_prefix:n #1
            {
            exp_args:Nf __nebu_prefix:n
            { exp_args:Nf fp_to_scientific:n { tl_lower_case:n {#1} } }
            }
            cs_new:Npn __nebu_prefix:n #1
            { __nebu_prefix:nwnw #1 q_stop }
            cs_new:Npn __nebu_prefix:nwnw #1 e #2 q_stop
            { __nebu_find_prefix:nnn {#2} {#1} {1} }
            cs_new:Npn __nebu_find_prefix:nnn #1 #2 #3
            {
            tl_if_exist:cT { l__nebu_ #1 tl_use:N l__nebu_mode_tl _prefix_tl }
            {
            use_i_delimit_by_q_stop:nw
            { __nebu_output:nnn {#2} {#1} {#3} }
            }
            int_compare:nNnT {#1} < l__nebu_min_prefix_int
            {
            use_i_delimit_by_q_stop:nw
            {
            exp_args:Nf __nebu_find_prefix:nnn
            { int_eval:n {#1+1} } {#2} {#3/10}
            }
            }
            use_i:nn
            {
            exp_args:Nf __nebu_find_prefix:nnn
            { int_eval:n {#1-1} } {#2} {#3*10}
            }
            q_stop
            }
            exp_args_generate:n { fv }
            cs_new:Npn __nebu_output:nnn #1 #2 #3
            {
            exp_args:Nfv nebu_output:nn
            { fp_to_decimal:n {#1*#3} } { l__nebu_ #2 tl_use:N l__nebu_mode_tl _prefix_tl }
            }
            cs_new_protected:Npn nebu_prefix_set:Nnn #1 #2 #3
            {
            exp_args:Nxx __nebu_prefix_set:nnN
            { tl_trim_spaces:n {#2} } { int_eval:n {#3} } #1
            }
            cs_new_protected:Npn __nebu_prefix_set:nnN #1 #2 #3
            {
            tl_clear_new:c { l__nebu_ #2 _prefix_tl }
            tl_clear_new:c { l__nebu_ #2 _siunitx_prefix_tl }
            tl_set:cn { l__nebu_ #2 _prefix_tl } {#1}
            tl_set:cn { l__nebu_ #2 _siunitx_prefix_tl } {#3}
            int_set:Nn l__nebu_min_prefix_int { int_min:nn {#2} { l__nebu_min_prefix_int } }
            }
            % User interface
            NewExpandableDocumentCommand prefix { m }
            { nebu_prefix:n {#1} }
            cs_new:Npn nebu_output:nn #1 #2 { #1, textrm{#2} }
            NewDocumentCommand setprefix { m m m }
            { nebu_prefix_set:Nnn #1 {#2} {#3} }
            DeclareSIPrefix none { } { 0 }
            setprefix none { } { 0 }
            %
            cs_new_protected:Npn __nebu_store:nn #1 #2
            {
            tl_set:Nn l__nebu_base_number_tl {#1}
            cs_set:Npn prefix {#2}
            }
            NewExpandableDocumentCommand prefixSI { o m o m }
            {
            group_begin:
            cs_set_eq:NN nebu_output:nn __nebu_store:nn
            tl_set:Nn l__nebu_mode_tl { _siunitx }
            nebu_prefix:n {#2}
            SI [#1] { l__nebu_base_number_tl } [#3] {#4}
            group_end:
            }
            ExplSyntaxOff

            setprefix yocto { y } { -24 }
            setprefix zepto { z } { -21 }
            setprefix atto { a } { -18 }
            setprefix femto { f } { -15 }
            setprefix pico { p } { -12 }
            setprefix nano { n } { -9 }
            setprefix micro { SIUnitSymbolMicro } { -6 }
            setprefix milli { m } { -3 }
            setprefix centi { c } { -2 }
            setprefix deci { d } { -1 }
            setprefix deca { da } { 1 }
            setprefix hecto { h } { 2 }
            setprefix kilo { k } { 3 }
            setprefix mega { M } { 6 }
            setprefix giga { G } { 9 }
            setprefix tera { T } { 12 }
            setprefix peta { P } { 15 }
            setprefix exa { E } { 18 }
            setprefix zetta { Z } { 21 }
            setprefix yotta { Y } { 24 }

            begin{document}
            prefix{1}par
            prefix{4E6}par
            prefix{1E-15}par
            prefix{1e-6}par
            prefix{300}par
            prefix{1000000}par
            prefix{.001}par
            prefix{.000004}par
            prefix{1E5}par
            prefix{10000}par
            prefix{.0001}par
            prefix{5E7}par
            prefix{1E-5}par
            prefix{3E8}par
            prefix{1E-4}par
            prefix{1E-24}par
            prefix{1E-28}par
            prefix{1E24}par
            prefix{1E28}par
            prefix{1e3*pi}par
            prefixSI{1e3*pi}{prefixmetre}par
            end{document}



            enter image description here








            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited 6 hours ago

























            answered 6 hours ago









            Phelype OleinikPhelype Oleinik

            30.1k6 gold badges50 silver badges103 bronze badges




            30.1k6 gold badges50 silver badges103 bronze badges













            • How would 10E-4 metres look? ;-) Great answer!

              – N3buchadnezzar
              6 hours ago






            • 1





              @N3buchadnezzar Thanks! A millimetre: 1 mm? Is there something wrong?

              – Phelype Oleinik
              6 hours ago



















            • How would 10E-4 metres look? ;-) Great answer!

              – N3buchadnezzar
              6 hours ago






            • 1





              @N3buchadnezzar Thanks! A millimetre: 1 mm? Is there something wrong?

              – Phelype Oleinik
              6 hours ago

















            How would 10E-4 metres look? ;-) Great answer!

            – N3buchadnezzar
            6 hours ago





            How would 10E-4 metres look? ;-) Great answer!

            – N3buchadnezzar
            6 hours ago




            1




            1





            @N3buchadnezzar Thanks! A millimetre: 1 mm? Is there something wrong?

            – Phelype Oleinik
            6 hours ago





            @N3buchadnezzar Thanks! A millimetre: 1 mm? Is there something wrong?

            – Phelype Oleinik
            6 hours ago


















            draft saved

            draft discarded




















































            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.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f497228%2fautomatically-convert-a-number-to-use-the-correct-si-unit-prefix%23new-answer', 'question_page');
            }
            );

            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







            Popular posts from this blog

            Taj Mahal Inhaltsverzeichnis Aufbau | Geschichte | 350-Jahr-Feier | Heutige Bedeutung | Siehe auch |...

            Baia Sprie Cuprins Etimologie | Istorie | Demografie | Politică și administrație | Arii naturale...

            Nicolae Petrescu-Găină Cuprins Biografie | Opera | In memoriam | Varia | Controverse, incertitudini...