Страницы: 1
RSS
Изменение счетчика цикла внутри цикла
 
Доброго времени суток

Интересует вот какой вопрос:

методом хорд я нахожу решение уравнения f(x) - C = 0 и строю его график. Делаю это в интервале от 5 до 40:

Код
For X = 5 To 40 Step 0.25
    
Q_guess1 = 0.95 * Q_guess3
Q_guess2 = 0.87 * Q_guess3
A1 = f(x, Q_guess1) - C
A2 = f(x, Q_guess2) - C
Q_guess3 = Q_guess2 - A2 * (Q_guess2 - Q_guess1) / (A2 - A1) 'хорды
A3 =  f(x, Q_guess3) - C

For i = 1 To 100
    If Abs(A1) > Abs(A2) Then 'удаление лишнего начального приближения
        Q_guess1 = Q_guess3
        A1 = A3
        Else
        Q_guess2 = Q_guess3
        A2 = A3
    End If
    If Abs(Q_guess1 - Q_guess2) < 1 Or Q_guess1 < 0 Or Q_guess2 < 0 Then
    Exit For 'критерий останова
    End If
     Q_guess3 = Q_guess2 - A2 * (Q_guess2 - Q_guess1) / (A2 - A1) 'новое значение Q_guess3
    A3 = f(x, Q_guess3) - C
Next i

Next X


кратко код выглядит так. все работает, нареканий нет, свое дело делает. но кривая с шагом 0.25 в интервале от 5 до 40 не нужна. мельчение нужно на определенном интервале, где f(x) ведет себя плохо (это вызвано приближенностью формулы, к делу отношения не имеет). и вот как бы сделать так, чтобы с начала и, допустим, до Х=20 шаг был равен 1, а потом менялся на 0.1?

я пытался делать так:
Код
For X = 5 To 40 Step Step_123
....
If x>20 then Step_123 = ..


Это не работало. Разбивать цикл на 2 - с 5 до 20 и с 20 до 40 тоже не хочется. гугл мне говорил, что это невозможно сделать, но, может быть, гуру знают больше гугла?)
Изменено: peat - 17.10.2013 22:54:58
 
Может быть внутри основного цикла после какого-то значения запускать вложенный?
 
Юрий М, вложенный будет копией основного, только интервал другой? по сути, это будут те же 2 цикла, про которые я писал, но элегантнее, спасибо)
 
Для начала отказаться от:
Цитата
Изменение счетчика цикла внутри цикла
переверните форум, никто так не делает. Хватает штатных if & case & exit. Файлом делиться не хотите - не надо. Нам хватит задач и от других гостей.
Я сам - дурнее всякого примера! ...
 
KuklP, зачем вам файл? он перегружен ничем не примечательным кодом. похожие на представленную выше штуки делаются там неоднократно, мне только дольше будет объяснять, что и где. я представил вам кусок кода, в котором собака и зарыта.

но вот вам полная версия функции) функция добавляет кривую на график, в файле никакой необходимости нет. получаемые функцией значения я в дальнейшем использую для расчетов, функция вызывается один раз.
Скрытый текст
 
Цитата
KuklP
Изменение счетчика цикла внутри цикла - никто так не делает.
peat!
Обратите пристальное внимание на это замечание KuklP!
Такие вещи были допустимы во времена Царя-Косаря: в эпоху зарождения "кодового" программирования.
Сегодня в арсенале любого языка море возможностей, с помощью которых можно избавиться от такой "кустарщины".
 
Мотя, я согласен, но конкретнее можно выразить совет?)
 
Цитата
KuklP
Хватает штатных if & case & exit.
:D
Очень даже КОНКРЕТНО!
 
Цитата
Такие вещи были допустимы во времена Царя-Косаря
Мотя, а что постыдного во вложенном цикле?
 
В мою студенческую бытность в Универах программированию на конкретных языках не обучали...
Обучали только структурному (см. определение) программированию без акцента на конкретные языки программирования.
И жестко исповедовали принцип: "программированию на конкретном языке и козу научить можно"!
 
Не увидел ответа на свой вопрос))
Я что предлагаю: по достижению некого значения первого счётчика запускается второй цикл (с другим счётчиком), который "побежит" быстрее.
 
Цитата
Юрий М
Не увидел ответа на свой вопрос))
А что постыдного во вложенном цикле?
Вопрос теоретический. :D

Цитата
Юрий М
второй цикл (с другим счётчиком)
Ваше предложение совпадает с предложением KuklP! :D
 
Ну да :-) - я пытался помочь вот с этим:
Цитата
Разбивать цикл на 2 - с 5 до 20 и с 20 до 40 тоже не хочется. гугл мне говорил, что это невозможно
Потому и предлагаю что-то вроде этого (для наглядности пусть будет перебор ячеек на листе):
Код
Private Declare Sub Sleep Lib "kernel32.dll" (ByVal dwMilliseconds As Long)

Sub Test()
Dim i As Integer, j As Integer
    For i = 1 To 11
        If i = 11 Then
            For j = 11 To 30
                Cells(j, 1).Select
                Sleep 100
            Next
            Exit For
        End If
        Cells(i, 1).Select
        Sleep 250
    Next
End Sub
 
Первую треть пути пройдём медленно, а потом бегом)))
 
Юрий М!
В своем сообщении №2 Вы не проявили категоричность, столь необходимую в тот момент. :D
 
Характер мягкий)) Хотя, по сути - это два последовательных цикла...
 
самое лучшее - два цикла. не могу понять чем это вам не нравится..

можно , конечно, внутри одного цикла ввести доп переменную для шага функции, но ее на каждом шаге цикла придется вычислять - это дополнительные затраты( времени).

for X= 5 to 40

dx=iif(X<20,X,20+0.1*X)
Живи и дай жить..
 
Слэн, думал, есть что-то интереснее 2 циклов. на самом деле, у меня там столько всего считается, что лишняя переменная будет не заметна, но вот если получится увеличить шаг на одном интервале, то это очень много сэкономит)
выше поднимался термин структурного программирования, мне вот как раз и хотелось бы узнать, как правильнее решить эту задачу)
 
Цитата
методом хорд
вы уверены?
а то я немножко засомневался: http://ru.wikipedia.org/wiki/Метод_хорд
в приведенном там коде на Си вообще нет никакого шага.
ни большого, ни маленького...
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
ikki, я применяю метод хорд не один раз, а несколько, изменяя х от 5 до 40)
 
а...
виноват, прошу прощения.
вопрос снимается.
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
ikki
какие проблемы)
другие функции, вычисляющие подобные кривые, построены как раз на do...while, но здесь, из-за плохой физичности функции, приходится использоваться for i = 1 to 100 т.к. на некоторых объектах (а программа используется для обработки более 100 объектов) прога зависала при зацикливании метода хорд, поэтому для этой функции пришлось сделать такой вот костыль - при зацикливании увеличивать эпсилон)
 
как вариант - использовать цикл do ... while
Код
x=5
do
    ' тело цикла...
    if x<20 then x=x+1 else x=x+0.1
loop while x<40
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
ikki
выглядит интересно, спасибо большое!
 
та же проблема - на каждом шаге происходит вычисление: if x<20 then x=x+1 else x=x+0.1

все таки.., не могу понять - чем два цикла-то не нравятся?  это наименьшие потери скорости..
Живи и дай жить..
 
Слэн
под f(x) скрыты десятки переменных и кучи строк арифметических операций, так что вычисляя на каждом шаге одну переменную, я сэкономлю лишний расчет десятков других)
два цикла не так красиво, на мой взгляд)) но есть еще и практическая причина - перед next я делую вот что:

Код
....
NK_Y(j) = Q_guess3
NK_X(j) = P_tr
j = j + 1
Next P_tr


при 2 циклах эта конструкция явно усложнится. и я даже думать боюсь как)
для чего все это вообще: процедура, вызываемая по кнопке юзером, открывает файл (особый для каждого объекта), ищет там лист-диграмму (оффтоп - может быть, вы знаете, как одной строкой искать именно лист-диаграмму? а то я ищу его по имени, если нет такого - вываливается инпут бокс. и проблема в том, что лист иногда называется отлично от стандарта, но никогда не бывает 2 листа-диаграммы), на диаграмме ищется кривая, сдираются х,у точек этой прямой и она сама. затем вызываются функции, аналогичные рассматриваемой, каждая из них строит кривую на этом же графике и каждая из них после вызова передает свои х, у

Код
NK(1, 1) = newNK_X
NK(1, 2) = newNK_Y
Q_guess_NK = NK


вот таким вот корявым способом, после этого прога ищет точки пересечения построенных кривых и той кривой, которая содрана с файла.
Страницы: 1
Читают тему
Наверх