List 如何在Tcl中生成数字序列
我正在寻找一种根据输入的List 如何在Tcl中生成数字序列,list,numbers,tcl,generator,sequence,List,Numbers,Tcl,Generator,Sequence,我正在寻找一种根据输入的from、to和步骤参数生成数字列表的方法 使用incr是不好的,因为我也想支持float和double数字 例如,如果from=-0.3,to=0.25和step=0.1,我想生成列表-0.3-0.2-0.1 0.2。我在格式化和舍入方面遇到问题。如果您可以自己删除字符串前缀: proc genNums {{from 0} {to 1} {step .1} {prec 1}} { if {$step < 0} { set op ::tcl:
from
、to
和步骤
参数生成数字列表的方法
使用incr
是不好的,因为我也想支持float
和double
数字
例如,如果
from=-0.3
,to=0.25
和step=0.1
,我想生成列表-0.3-0.2-0.1 0.2
。我在格式化和舍入方面遇到问题。如果您可以自己删除字符串前缀:
proc genNums {{from 0} {to 1} {step .1} {prec 1}} {
if {$step < 0} {
set op ::tcl::mathop::>
} else {
set op ::tcl::mathop::<
}
for {set n $from} {[$op $n $to]} {set n [expr {$n + $step}]} {
lappend res [format %.*f $prec $n]
}
return $res
}
% genNums -0.3 0.25 0.1
# => -0.3 -0.2 -0.1 0.0 0.1 0.2
% genNums -0.3 0.25 0.1 2
# => -0.30 -0.20 -0.10 0.00 0.10 0.20
proc genNums{{from 0}{to 1}{step.1}{prec 1}}{
如果{$step<0}{
set op::tcl::mathop::>
}否则{
set op::tcl::mathop::<
}
对于{set n$from}{[$op$n$to]}{set n[expr{$n+$step}]}{
lappend res[格式%.*f$prec$n]
}
返回$res
}
%genNums-0.30.25 0.1
# => -0.3 -0.2 -0.1 0.0 0.1 0.2
%genNums-0.30.25 0.1 2
# => -0.30 -0.20 -0.10 0.00 0.10 0.20
但如果需要,可以对其进行设置,以便将字符串传递给命令:
proc genNums args {
array set params {from 0 to 1 step .1 prec 1}
array set params [split [string map {= { }} $args]]
if {$params(step) < 0} {
set op ::tcl::mathop::>
} else {
set op ::tcl::mathop::<
}
for {set n $params(from)} {[$op $n $params(to)]} {set n [expr {$n + $params(step)}]} {
lappend res [format %.*f $params(prec) $n]
}
return $res
}
genNums from=-0.3 to=0.25 step=0.1
# => -0.3 -0.2 -0.1 0.0 0.1 0.2
% genNums from=-0.3 to=0.25 step=0.1 prec=2
# => -0.30 -0.20 -0.10 0.00 0.10 0.20
proc genNums args{
数组集参数{从0到1步骤.1 prec 1}
数组集参数[split[string map{={}}$args]]
如果{$params(步骤)<0}{
set op::tcl::mathop::>
}否则{
set op::tcl::mathop::<
}
对于{set n$params(from)}{[$op$n$params(to)]}{set n[expr{$n+$params(step)}]}{
lappend res[格式%.*f$params(prec)$n]
}
返回$res
}
genNums from=-0.3到=0.25步=0.1
# => -0.3 -0.2 -0.1 0.0 0.1 0.2
%genNums from=-0.3至=0.25步数=0.1 prec=2
# => -0.30 -0.20 -0.10 0.00 0.10 0.20
文件:
,
,
,
,
,
,
,
,
,
,
,
,
这是一个很好的例子。真的
您需要做的是使用整数迭代,然后按步长缩放。这样可以最大限度地减少错误。您还需要小心地使用格式
set from -0.3
set to 0.25
set step 0.1
for {set i 0} true {incr i} {
set x [expr {$i*$step + $from}]
if {$x > $to} break
set printable [format "%.1f" $x]
puts "$i => $printable"
}
您如何看待以下解决方案:
proc ::General::Range {Start Stop {Step 1}} {
if {$Step eq 0} {return Error-'ZeroStep'}
if {$Start eq $Stop} {return $Start}
set Range {}
if {![string in integer $Step]} {
# Double
regexp {^\d+\.(\d+)$} $Step FullMatch ToFormat
while {$Start <= $Stop} {
lappend Range [string trimright $Start 0]
set Start [format "%.${ToFormat}f" [expr {$Start + $Step}]]
}
} else {
# Integer
while {[expr {$Stop > 0 ? [expr {$Start <= $Stop}] : [expr {$Start >= $Stop}]}]} {lappend Range $Start; incr Start $Step}
}
return $Range
}
proc::General::Range{Start-Stop{Step 1}{
如果{$Step eq 0}{返回错误-'ZeroStep'}
如果{$Start eq$Stop}{return$Start}
设置范围{}
如果{![string in integer$Step]}{
#双重的
regexp{^\d+\(\d+$}$步骤完全匹配到格式
而{$Start 0?[expr{$Start=$Stop}]}{lappend Range$Start;incr Start$Step}
}
返回$Range
}
下面是一个示例,使用Tcl的协同程序按需生成范围内的下一个值
% proc range {from to step} {
yield
set value $from
while {$value <= $to} {
yield $value
set value [expr {$value + $step}]
}
}
% coroutine generator range -0.35 0.25 0.1
% puts [generator]
-0.35
% puts [generator]
-0.24999999999999997
% puts [generator]
-0.14999999999999997
% puts [generator]
-0.04999999999999996
% puts [generator]
0.050000000000000044
% puts [generator]
0.15000000000000005
% puts [generator]
% puts [generator]
invalid command name "generator"
我们得到了序列
-0.35
-0.24999999999999997
-0.14999999999999997
-0.04999999999999993
0.050000000000000044
0.15000000000000002
0.2500000000000001
这假设步骤
为正;如果step
为负值,测试的意义将需要改变。我不应该根据step分辨率推导小数点位置吗?严格来说是的,但通常只需硬编码就可以了。(set decimalPlaces 1;format%.*f$decimalPlaces$x
)此函数不执行此任务,例如,使用from=-0.35
to=0.75
和step=0.1
。它产生-0.3-0.2-0.1-0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7
@HardwareEng.:您期望的序列是什么?请注意,这是一个小数点:将格式设置为%.2f
可能更好。@peter,可以添加一个scale=2
参数,您可以在format命令中使用它。如果要与0进行比较,请使用=
;0.0不是eq
到0。在
命令中没有字符串,您可能的意思是字符串是
。非整数步长不能为负<代码>字符串trimright$Start 0
意味着您将得到以小数点结尾的数字。从步长值获取格式精度将导致一些奇怪的格式设置。您不必根据Stop
的值来决定计数是向上还是向下。此外,您过度使用了expr
,使代码更难阅读。这样做并没有实际的好处。@PeterLewerin:谢谢你的见解@谢谢你的见解!
-0.35
-0.24999999999999997
-0.14999999999999997
-0.04999999999999993
0.050000000000000044
0.15000000000000002
0.2500000000000001