Как сгенерировать последовательность чисел в Tcl

list numbers tcl generator sequence

2611 просмотра

4 ответа

54 Репутация автора

Я ищу способ создания списка чисел, в соответствии с входом from, toи stepпараметрами.

Использование incrне годится, так как я хотел бы также поддерживать floatи doubleцифры.

Например, в случае from=-0.3, to=0.25и step=0.1я хотел бы создать список -0.3 -0.2 -0.1 0 0.1 0.2. У меня проблемы с форматированием и округлением.

Автор: HardwareEng. Источник Размещён: 18.07.2016 11:34

Ответы (4)


1 плюс

12396 Репутация автора

Если вы можете удалить строковые префиксы самостоятельно:

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 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

Документация: + (оператор) , <(оператор) , массив , expr , for , формат , if , lappend , proc , return , set , split , string , математические операторы как команды Tcl

Автор: Peter Lewerin Размещён: 18.07.2016 12:06

2 плюса

108176 Репутация автора

Это классическая проблема в вычислительной технике . Шутки в сторону.

Что вам нужно сделать, так это использовать целочисленную итерацию, а затем масштабировать до размера шага. Это минимизирует ошибки. Вы также должны использовать formatосторожно.

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"
}
Автор: Donal Fellows Размещён: 18.07.2016 12:06

0 плюса

54 Репутация автора

Что вы думаете о следующем решении:

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
}
Автор: HardwareEng. Размещён: 18.07.2016 12:29

0 плюса

180878 Репутация автора

Вот пример использования сопрограмм 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"

Как говорил Донал, здесь мы видим накапливающиеся ошибки с плавающей запятой. Применяя его метод:

proc range {from to step} {
    yield
    set i 0
    while 1 {
        set value [expr {$from + $i * $step}]
        yield $value
        if {$value > $to} break
        incr i
    }
}

мы получаем последовательность

-0.35
-0.24999999999999997
-0.14999999999999997
-0.04999999999999993
0.050000000000000044
0.15000000000000002
0.2500000000000001
Автор: glenn jackman Размещён: 18.07.2016 06:08
Вопросы из категории :
32x32