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;
}
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
|
show 4 more comments
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
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 withsiunitx
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
|
show 4 more comments
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
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
siunitx number
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 withsiunitx
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
|
show 4 more comments
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 withsiunitx
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
|
show 4 more comments
3 Answers
3
active
oldest
votes
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}
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}
Awesome! Now all that remains is for someone to figure out how to convertprefix{10000}
to10k
=)
– N3buchadnezzar
10 hours ago
1
@N3buchadnezzar Ask and ye shall receive. Done.
– Steven B. Segletes
9 hours ago
add a comment |
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}
add a comment |
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}
How would10E-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
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "85"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%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
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}
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}
Awesome! Now all that remains is for someone to figure out how to convertprefix{10000}
to10k
=)
– N3buchadnezzar
10 hours ago
1
@N3buchadnezzar Ask and ye shall receive. Done.
– Steven B. Segletes
9 hours ago
add a comment |
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}
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}
Awesome! Now all that remains is for someone to figure out how to convertprefix{10000}
to10k
=)
– N3buchadnezzar
10 hours ago
1
@N3buchadnezzar Ask and ye shall receive. Done.
– Steven B. Segletes
9 hours ago
add a comment |
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}
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}
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}
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}
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 convertprefix{10000}
to10k
=)
– N3buchadnezzar
10 hours ago
1
@N3buchadnezzar Ask and ye shall receive. Done.
– Steven B. Segletes
9 hours ago
add a comment |
Awesome! Now all that remains is for someone to figure out how to convertprefix{10000}
to10k
=)
– 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
add a comment |
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}
add a comment |
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}
add a comment |
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}
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}
answered 7 hours ago
egregegreg
750k89 gold badges1964 silver badges3307 bronze badges
750k89 gold badges1964 silver badges3307 bronze badges
add a comment |
add a comment |
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}
How would10E-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
add a comment |
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}
How would10E-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
add a comment |
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}
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}
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 would10E-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
add a comment |
How would10E-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
add a comment |
Thanks for contributing an answer to TeX - LaTeX Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f497228%2fautomatically-convert-a-number-to-use-the-correct-si-unit-prefix%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
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