TransWikia.com

Discrete range/interval in siunitx

TeX - LaTeX Asked on April 3, 2021

Using siunitx, I can type $V = SIrange[range-phrase=text{ to },range-units=single]{100}{125}{kilomperhour}$ to get

enter image description here

However, numerically speaking, I have to specify the step of the range in order to know exactly each speed value I will do my calculations at.

Therefore, I would like to understand how to create a command, e.g. SIsteps, where it accepts the following arguments:

<start>,

<step> (optional and its default is 1) it can be integer or float,

<size> (optional) it is the total number of the elements in the range/interval

<end>, and

<unit>.

So, for example, all the following codes should have the same output of

enter image description here

The speed range is $V = SIsteps[step=5]{100}{125}{km}$

The speed range is $V = SIsteps[size=6]{100}{}{km}$

The speed range is $V = SIsteps[size=6]{}{125}{km}$

documentclass{article}
usepackage{unicode-math,siunitx}
sisetup{
    load-configurations = abbreviations,
    inter-unit-product = ensuremath{{hspace{-0.5ex}}cdot{hspace{-0.5ex}}}
}
setmathfont{Cambria Math}
begin{document}
The speed range is $V = left{100,105,ldots,125right}~si{kmperhour}$
end{document}

One Answer

The macro SIsteps has

  1. an optional argument for options to be passed to num
  2. a mandatory argument with options for the steps
  3. an optional argument with options for si
  4. a mandatory argument for the unit

As you requested, the default step is 1, but it can be specified either in the options or (following normal scope rules) with stepsetup.

The keys are

  • start to set the starting point
  • end to set the end point
  • step to set the step
  • size to set the number of items to show
  • full to specify we want a full display of the values (default false)
  • sep to specify the separator between items (default comma)

You have better to specify two keys among start, end and size, but don't specify all three of them.

documentclass{article}
usepackage{siunitx,xfp}

sisetup{
    load-configurations = abbreviations,
    inter-unit-product = ensuremath{{cdot}}
}


ExplSyntaxOn

keys_define:nn { diaa/steps }
 {
  start .fp_set:N   = l__diaa_steps_start_fp,
  start .initial:n  = -c_inf_fp,
  end   .fp_set:N   = l__diaa_steps_end_fp,
  end   .initial:n  = c_inf_fp,
  step  .fp_set:N   = l__diaa_steps_step_fp,
  step  .initial:n  = 1,
  size  .int_set:N  = l__diaa_steps_size_int,
  full  .bool_set:N = l__diaa_steps_full_bool,
  full  .initial:n  = false,
  full  .default:n  = true,
  sep   .tl_set:N   = l__diaa_steps_sep_tl,
  sep   .initial:n  = {,},
 }

NewDocumentCommand{SIsteps}{O{}mO{}m}
 {
  group_begin:
  keys_set:nn { diaa/steps } { #2 }
  int_compare:nT { l__diaa_steps_size_int > 0 }
   {% size has been specified
    fp_compare:nTF { l__diaa_steps_end_fp = c_inf_fp }
     {% end has not been specified
      fp_set:Nn l__diaa_steps_end_fp
       {
        l__diaa_steps_start_fp + (l__diaa_steps_size_int-1)*l__diaa_steps_step_fp
       }
     }
     {% start has not been specified
      fp_set:Nn l__diaa_steps_start_fp
       {
        l__diaa_steps_end_fp - (l__diaa_steps_size_int-1)*l__diaa_steps_step_fp
       }
     }
   }
  ensuremath
   {
    {
    bool_if:NTF l__diaa_steps_full_bool
     {% full display
      fp_step_inline:nnnn
       { l__diaa_steps_start_fp } % start
       { l__diaa_steps_step_fp } % step
       { l__diaa_steps_end_fp - l__diaa_steps_step_fp } % end
       {
        num[#1]{ fp_eval:n { ##1 } } l__diaa_steps_sep_tl
       }
       num[#1]{ fp_eval:n { l__diaa_steps_end_fp } }
     }
     {% short display
      num[#1]{ fp_eval:n { l__diaa_steps_start_fp } }
      l__diaa_steps_sep_tl
      num[#1]{ fp_eval:n { l__diaa_steps_start_fp + l__diaa_steps_step_fp } }
      l__diaa_steps_sep_tl
      dotsl__diaa_steps_sep_tl
      num[#1]{ fp_eval:n { l__diaa_steps_end_fp } }
     }
    }
    ,si[#3]{#4}
   }
  group_end:
 }
NewDocumentCommand{stepsetup}{m}
 {
  keys_set:nn { diaa/steps } { #1 }
 }

ExplSyntaxOff

begin{document}

The speed range is $V = SIsteps{step=5,start=100,end=125}{kmperhour}$

The speed range is $V = SIsteps{size=6,start=100}{kmperhour}$ % step is one

The speed range is $V = SIsteps{size=6,start=100,step=5}{kmperhour}$

stepsetup{step=5}

The speed range is $V = SIsteps{size=6,end=125}{kmperhour}$

The speed range is $V = SIsteps{size=6,end=125,full,sep={;}}{kmperhour}$

end{document}

enter image description here

The explicit , between the brace and the unit might be l__siunitx_number_unit_product_tl, but this is an internal of siunitx and it's bad practice to use it. This might possibly be offered as a user level token list in the future.

You can also add support for angles (but not minutes and seconds, for that you'd be charged a thousand times).

documentclass{article}
usepackage{siunitx,xfp}

sisetup{
    load-configurations = abbreviations,
    inter-unit-product = ensuremath{{cdot}}
}


ExplSyntaxOn

keys_define:nn { diaa/steps }
 {
  start .fp_set:N   = l__diaa_steps_start_fp,
  start .initial:n  = -c_inf_fp,
  end   .fp_set:N   = l__diaa_steps_end_fp,
  end   .initial:n  = c_inf_fp,
  step  .fp_set:N   = l__diaa_steps_step_fp,
  step  .initial:n  = 1,
  size  .int_set:N  = l__diaa_steps_size_int,
  full  .bool_set:N = l__diaa_steps_full_bool,
  full  .initial:n  = false,
  full  .default:n  = true,
  sep   .tl_set:N   = l__diaa_steps_sep_tl,
  sep   .initial:n  = {,},
 }

NewDocumentCommand{SIsteps}{O{}mO{}m}
 {
  group_begin:
  diaa_sisteps:nnnnNn { #1 } { #2 } { #3 } { #4 }
                       num 
                       { l__siunitx_number_unit_product_tl si[#3]{#4} }
  group_end:
 }
NewDocumentCommand{anglesteps}{O{}mO{}}
 {
  group_begin:
  diaa_sisteps:nnnnNn { #1 } { #2 } { #3 } { }
                       ang 
                       { }
  group_end:
 }

cs_new_protected:Nn diaa_sisteps:nnnnNn
 {
  keys_set:nn { diaa/steps } { #2 }
  int_compare:nT { l__diaa_steps_size_int > 0 }
   {% size has been specified
    fp_compare:nTF { l__diaa_steps_end_fp = c_inf_fp }
     {% end has not been specified
      fp_set:Nn l__diaa_steps_end_fp
       {
        l__diaa_steps_start_fp + (l__diaa_steps_size_int-1)*l__diaa_steps_step_fp
       }
     }
     {% start has not been specified
      fp_set:Nn l__diaa_steps_start_fp
       {
        l__diaa_steps_end_fp - (l__diaa_steps_size_int-1)*l__diaa_steps_step_fp
       }
     }
   }
  ensuremath
   {
    {
    bool_if:NTF l__diaa_steps_full_bool
     {% full display
      fp_step_inline:nnnn
       { l__diaa_steps_start_fp } % start
       { l__diaa_steps_step_fp } % step
       { l__diaa_steps_end_fp - l__diaa_steps_step_fp } % end
       {
        #5[#1]{ fp_eval:n { ##1 } } l__diaa_steps_sep_tl
       }
       #5[#1]{ fp_eval:n { l__diaa_steps_end_fp } }
     }
     {% short display
      #5[#1]{ fp_eval:n { l__diaa_steps_start_fp } }
      l__diaa_steps_sep_tl
      #5[#1]{ fp_eval:n { l__diaa_steps_start_fp + l__diaa_steps_step_fp } }
      l__diaa_steps_sep_tl
      fp_compare:nT
       { (l__diaa_steps_end_fp-l__diaa_steps_start_fp)/l__diaa_steps_step_fp > 3 }
       { dotsl__diaa_steps_sep_tl }
      #5[#1]{ fp_eval:n { l__diaa_steps_end_fp } }
     }
    }
    #6
   }
 }
NewDocumentCommand{stepsetup}{m}
 {
  keys_set:nn { diaa/steps } { #1 }
 }

ExplSyntaxOff

begin{document}

The speed range is $V = SIsteps{step=5,start=100,end=125}{kmperhour}$

The speed range is $V = SIsteps{size=6,start=100}{kmperhour}$ % step is one

The speed range is $V = SIsteps{size=6,start=100,step=5}{kmperhour}$

The speed range is $V = SIsteps{size=6,start=84.37,step=5}{kmperhour}$

stepsetup{step=5}

The speed range is $V = SIsteps{size=6,end=125}{kmperhour}$

The speed range is $V = SIsteps{size=6,end=125,full,sep={;}}{kmperhour}$

The speed range is $V = SIsteps{step=5,start=20,end=30}{kmperhour}$

stepsetup{step=1}

Angle ranges:

anglesteps{step=5,start=100,end=125}

anglesteps{size=6,start=100}

anglesteps{size=6,start=100,step=5}

anglesteps{size=6,start=84.37,step=5}

stepsetup{step=5}

anglesteps{size=6,end=125}

anglesteps{size=6,end=125,full,sep={;}}

anglesteps{step=5,start=20,end=30}

end{document}

enter image description here

Correct answer by egreg on April 3, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP