正しいSI単位プレフィックスを使用するように数値を自動的に変換します



Automatically Convert Number Use Correct Si Unit Prefix



解決:

両方の入力フォームを解決するために編集されました。科学的記数法で大文字または小文字のEが許可されるように編集されました(例:1E6または1e6)。

標準単位で1、10、または100の乗数を自動的に識別するように編集されています。



プレフィックスが1E-24から1E26の範囲外の場合、??が出力されます。

見る 補足 乗数のより一般的な使用(1、10、100以外)。



この答えはEDITSで拡張されたので、ロジックを説明しましょう。互いに順番に呼び出す3つのマクロがあります。最後から最初まで頑張っていきましょう。最下位レベルのマクロは

 prefixSN [] {1E}

乗数のデフォルトは1ですが、10または100にすることができます。SIプレフィックス整数は、SIプレフィックスが定義されている特定の整数です(-24、-21、...- 6、-3、-2、-1)。 、0、1、2、3、6、... 21、24)。指定された整数がこのリストにない場合、??が出力されます。整数がリストにある場合、乗数の後に適切なSIプレフィックスが出力されます。

フィードするマクロ適切な構文の prefixSNが呼び出されます prefixmult、構文付き



 prefixmult {1E}

ここで、整数は-24〜26の範囲にある必要があります。整数の値に基づいて、プレフィックスを1、10、または100に設定し、整数を次に低いSI標準値に調整します。たとえば、 prefixmultは1E5、それは呼び出しを設定します prefixSI [100] {1E3}。

トップレベルのマクロ、フィードする prefix prefixmultその整数形式で、4つの可能な形式で入力を受け取ることができます。

 prefix {1E}  prefix {1e}  prefix {100}  prefix {.001}

それは探して分類しますEまたはe。 1つを見つけると、大文字のEフォームがに渡されます。 prefixmultと関連する整数。いいえの場合Eが見つかり、小数点を探します。1以上0トークン。見つかったものに基づいて、ゼロの数に基づいて関連する整数を再構築し、それをに渡します prefixmult。

これがMWEです。

 documentclass {article}  usepackage {siunitx、listofitems}  newcommand  prefixSN [2] [1] {#1 、 prefixSNaux#2  Relax}  def  prefixSNaux 1E#1  Relax {% ifnum#1 = 0  relax  else  ifnum#1 = -1  relax  textrm {d}  else  ifnum#1 = -2  relax  textrm {c}  else  ifnum#1 = -3  relax  textrm {m }  else  ifnum#1 = -6  relax  textrm { ensuremath { mu}}  else  ifnum#1 = -9  Relax  textrm {n}  else  ifnum#1 = -12  Relax  textrm {p}  else  ifnum#1 = -15  Relax  textrm {f}  else  ifnum#1 = -18  relax  textrm {a}  else  ifnum#1 = -21  Relax  textrm { z}  else  ifnum#1 = -24  relax  textrm {y}  else  ifnum#1 = 1  relax  textrm {da}  else  ifnum#1 = 2  relax  textrm {h}  else  ifnum#1 = 3  relax  textrm {k}  else  ifnum#1 = 6  relax  textrm {M}  else  ifnum#1 = 9  relax  textrm {G}  else  ifnum#1 = 12  relax  textrm {T}  else  ifnum#1 = 15  relax  textrm {P}  else  ifnum#1 = 18  relax  textrm {E}  else  ifnum#1 = 21  relax  textrm {Z}  else  ifnum#1 = 24  Relax  textrm {Y}  else ??% fi  fi  fi  fi  fi  fi  fi  fi  fi  fi  fi  fi  fi  fi  fi  fi  fi  fi  fi  fi  fi}  newcommand  prefix [1] {% setsepchar1e% readlist  scinot {#1}% ifnum  scinotlen> 1  Relax  itemt omacro  scinot [2]  temp% expandafter  prefixmult  expandafter { expandafter1  expandafter E  temp}% else  setsepchar {./1/0}% readlist  zerocount {#1}% ifnum  zerocountlen = 1  Relax  expandafter  prefixmult  expandafter { expandafter1  expandafter E% the  numexpr  listlen  zerocount [1,2] -1  Relax}% else  expandafter  prefixmult  expandafter { expandafter1  expandafter E % expandafter-  the  numexpr  listlen  zerocount [2,1]  Relax}% fi  fi}  newcommand  prefixmult [1] { prefixmultaux#1  Relax}  def  prefixmultaux 1E#1  Relax {% setsepcharE25% readlist  factormult {E#1}% ifnum  factormultlen> 1  Relax  prefixSN [10] {1E  the  numexpr#1-1  Relax}  else  setsepchar% readlist  factormult {E#1}% ifnum  factormultlen> 1  Relax  prefixSN [100] {1E  the  numexpr#1-2  Relax}  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}

ここに画像の説明を入力してください

補足

これが改善であるかどうかはわかりません。 prefixは、10の累乗のみで処理する必要があります。ただし、任意の乗数を処理できる、より一般的な実装が必要な場合 有効数字1桁の 、そしてここにあります:

 documentclass {article}  usepackage {siunitx、listofitems}  newcommand  prefixSN [2] [1] {#1 、 prefixSNaux#2  Relax}  def  prefixSNaux 1E#1  Relax {% ifnum#1 = 0  relax  else  ifnum#1 = -1  relax  textrm {d}  else  ifnum#1 = -2  relax  textrm {c}  else  ifnum#1 = -3  relax  textrm {m }  else  ifnum#1 = -6  relax  textrm { ensuremath { mu}}  else  ifnum#1 = -9  Relax  textrm {n}  else  ifnum#1 = -12  Relax  textrm {p}  else  ifnum#1 = -15  Relax  textrm {f}  else  ifnum#1 = -18  relax  textrm {a}  else  ifnum#1 = -21  Relax  textrm { z}  else  ifnum#1 = -24  relax  textrm {y}  else  ifnum#1 = 1  relax  textrm {da}  else  ifnum#1 = 2  relax  textrm {h}  else  ifnum#1 = 3  relax  textrm {k}  else  ifnum#1 = 6  relax  textrm {M}  else  ifnum#1 = 9  relax  textrm {G}  else  ifnum#1 = 12  relax  textrm {T}  else  ifnum#1 = 15  relax  textrm {P}  else  ifnum#1 = 18  relax  textrm {E}  else  ifnum#1 = 21  relax  textrm {Z}  else  ifnum#1 = 24  Relax  textrm {Y}  else ??% fi  fi  fi  fi  fi  fi  fi  fi  fi  fi  fi  fi  fi  fi  fi  fi  fi  fi  fi  fi  fi}  newcommand  prefix [1] {% setsepchare% readlist  scinot {#1}% ifnum  scinotlen> 1  Relax  itemto macro  scinot [1]  premult% itemtomacro  scinot [2]  temp% expandafter  expandafter  expandafter  prefixmult  expandafter  expandafter  expandafter {% expandafter  premult  expandafter E  temp}% else  setsepchar8 % readlist  zerocount {#1}% ifnum  zerocountlen = 1  Relax  expandafter  expandafter  expandafter  def  expandafter  expandafter  expandafter  temp  expandafter  expandafter  expandafter { zerocountsep [1,1]}%  expandafter  expandafter  expandafter  prefixmult  expandafter  expandafter  expandafter {% expandafter  temp  expandafter E% the  numexpr  listlen  zerocount [1,2] -1  Relax}% else  expandafter  expandafter  expandafter  def  expandafter  expandafter  expandafter  temp  expandafter  expandafter  expandafter { zerocountsep [2,1]}% expandafter  expandafter  expandafter  prefixmult  expandafter  expandafter  expandafter {% expandafter  temp  expandafter E % expandafter-  the  numexpr  listlen  zerocount [2,1]  Relax}% fi  fi}  newcommand  prefixmult [1] { prefixmultaux#1  Relax}  def  prefixmultaux#1E#2 リラックス{% setsepchar% readli st  factormult {E#2}% ifnum  factormultlen> 1  Relax  prefixSN [#10] {1E  the  numexpr#2-1  Relax}  else  setsepchar% readlist  factormult {E#2} % ifnum  factormultlen> 1  Relax  prefixSN [#100] {1E  the  numexpr#2-2  relax}  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}

ここに画像の説明を入力してください


これは、指数表記と標準表記の両方をサポートします。

ゼロ以外の数字に関するチェックは実行されず、入力は次の形式であると見なされます。

1 -1 1e 1E -1e -1E

範囲は-1E-26から1E26。この範囲外の数値は黙って失敗します。範囲に関する制御を追加できます。

コードは次のとおりです。作業の大部分はによって実行されることに注意してください __ nebuch_prefix_exp:nn(正確には:eeバリアント)。

 documentclass {article}  usepackage {siunitx}%はxparseと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} {%e / Eがあった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  neb_  __ 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}{
anovoidunit} {-2}{microvoidunit} {-1}{millivoidunit} {0}{!voidunit} {1}{kilovoidunit} {2}{megavoidunit} {3}{gigavoidunit} {4}{	eravoidunit} {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 
egex_split:nnN { (-*1+) } { #1 } l__nebuch_prefix_input_seq \__nebuch_prefix_exp:ee { seq_item:Nn l__nebuch_prefix_input_seq { 2 } } { 	l_count:e { seq_item:Nn l__nebuch_prefix_input_seq { 3 } } } } cs_generate_variant:Nn 	l_count:n { e } ExplSyntaxOff DeclareSIUnit{voidunit}{
elax} egin{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}  

ここに画像の説明を入力してください


これにより、任意の(もちろん有効な)値または式を入力できます。コード(ab)は、LaTeX3浮動小数点ユニットを使用して入力式を解析し、指数表記に変換します。これで、コードはその番号に適用する正しいプレフィックスを探すだけです。範囲外の数値は、最も近いプレフィックスに合うように、より多くの桁で出力されます( NS。、 1E28プリント10000Yおよび1E-28プリント0.0001および)。

NS prefixマクロ(おそらく呼び出されるはずです postfix :-)は展開可能で、1つの引数、数値を取り、それに続いて接頭辞を出力します。

NS prefixSIマクロは展開可能ではなく、と同じ署名を持っていますsiunitxの SIマクロ。 prefixSIは、最初の必須引数を次のように評価します。 prefix( nebu_prefix:n、実際には)、上記のように、それをに渡します SI。選択したプレフィックスはに保存されます prefix(グループ内で、 大きい prefixはagianで使用できます)これは、たとえば、単位式で使用できます prefixSI {1000} { prefix metre}は印刷します1キロ。

プレフィックスは次のように宣言できます setprefix {} {}、like setprefix centi {c} {-2}。確認してくださいが存在します。使用しない場合 prefixSI次に、使用できますそこにリラックス。

そして、コードが使用するように数値を解析するためのexpl3の浮動小数点ユニット。aEbまたは10進表記。で実装されている任意の浮動小数点演算を実行できますl3fp(それらのリストについてはここを見てください)のようにa * 10 ^ bまたはその他。

 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 { _ 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:nw #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} 

ここに画像の説明を入力してください