Excel это не сложно

Основные форумы => Вопросы по Excel и VBA => Тема начата: Игорюша от 22.01.2019, 12:54:51



Название: Цикл для функции y=x*0.2+x
Отправлено: Игорюша от 22.01.2019, 12:54:51
Доброго времени суток.
Хочу написать макрос, с циклом.
Который бы искал целое(до 4го знака после запятой) значение функции:
y=x*0,2+x.

Интервал: +3 к начальному значению, т.е.
 например:
x∈[15,31..18,31] .
Шаг 0,01
...
условно
x=17,47
17,47+0,01=17,48
y=17,48*0,2+17,48=20.976
Значение не целое, поэтому продолжаем цикл:
x=17,48+0,01=17,49
y=17,49*0,2+17,49=20.988
То же самое.
x=17,49+0,01=17,5
y=17,5*0,2+17,5=21
Наконец получили целое число.
Вывести в такую то ячейку.

Так вот, меня интересует, как правильно объяснить "машине", что она получила целое число и его нужно вернуть в нужную ячейку?
Надеюсь, правильно всё расписал)

Может у кого-нибудь даже  набросок примерно такого кода есть? Первый раз в жизни пытаюсь на ВБА что то писать.



Название: Re:Цикл для функции y=x*0.2+x
Отправлено: Дмитрий Щербаков(The_Prist) от 22.01.2019, 13:22:29
целое(до 4го знака после запятой)
Это что за целое такое? Целое - это вообще без знаков после запятой. Поэтому как-то расходится желание с пояснением. Да и +3 непонятно куда девать. Я вот не увидел для чего она вообще упомянута. Где должен принимать участие этот интервал?
И сходу вопрос: а если прибавление заданного значения вообще по условиям функции не может дать ровное целое число никогда? Что тогда? Вечное наслаждение процессом? :)
По факту проверить можно так:
Код: (vb)
yy=17,5*0,2+17,5
if int(yy) = yy then
msgbox "y равно целому: " & yy
y = yy
end if

Первый раз в жизни пытаюсь на ВБА что то писать
тогда циклы тоже придется осваивать с нуля. Если правильно понял, то в итоге должно быть нечто вроде:
Код: (vb)
Dim y As Double, yy As Double, x As Double
Dim lr As Long
x = 17.47
For lr = 0 To 300 'цикл от 0 до 300
    x = x + lr / 100 'прибавляем 0,01 к последнему значению x. С каждым циклом оно будет увеличиваться
    yy = x * 0.2 + x
    If Int(yy) = yy Then ' Int - спец.функция, которая отбрасывает дробную часть числа, оставляя только целую
        MsgBox "y равно целому: " & yy
        y = yy
        Exit For 'выходим из цикла принудительно, т.к. задача выполнена
    End If
Next


Название: Re:Цикл для функции y=x*0.2+x
Отправлено: Игорюша от 23.01.2019, 07:03:58
Большущенское спасибо, за ответ)
Ну это условно "целое", на самом деле меня интересует число, которое даже после округления не даст ничего кроме нулей, до 2х знаков после запятой.
Пример: 15,0012 , после округления оно будет целым(15,00).
А вот если число будет таким: 15,0045, то соответственно после округления у меня получится 15,01 и это мне уже не подойдёт.


Про "+3", ну да, по идее вы правы. Это условие можно опустить.
Вот тут не понял:
For lr = 0 To 300 'цикл от 0 до 300 
    x = x + lr / 100 , lr - это единица каждый цикл будет делится на 100, не будет же он после 1/100 , делить 2/100 и т.п. до 300 ?
Может Do While, тут должно подойти?

if int(yy) = yy then -  тут мне кажется программа будет выделять именно целое число, так?
А мне(повторюсь), нужно именно условно "целое", до 4х знаков после запятой, причём что бы 3й и 4й знаки после округления не могли передать на второй знак +1.
Наверное путано объясняю)


Да, с циклами я видимо ещё помучаюсь(
Получается мне ещё цикл в цикле что ли делать...
Мне нужно будет сделать так , что бы "поиск" шёл по одному столбцу, и вычисленное значение выписывал в соседнюю ячейку.
Но, пока меня интересует  цикл с вычислением и выполнение условия.


Название: Re:Цикл для функции y=x*0.2+x
Отправлено: Игорюша от 23.01.2019, 07:05:31
 Ну вобщем каша какая то получилась((

Код: (vb)
Dim y As Double, yy As Double, x As Double
    Dim lr As Double
    lr = 0.01
    x = Cells(i, 1)
    Do While Cells(i, 1) <> ""  ' тут первый цикл, где идёт выполнение условия:
    If Cells(i, 3) = "Число" Then ' если в 3м столбце есть слово "Число", тогда начинается расчёт.
    Do While yy = Double(yy)  ' тут не знаю, как написать делать пока не произойдёт что? Пока число при округлении до 2х знаков п.з. не даст только нули(при этом результат всё равно нужен именно с 4мя знаками п.з.)
    yy = Cells(i, 1) * 0.2 + Cells(i, 1)
    
    If Int(yy) = yy Then ' тут тоже не знал как ещё написать условие со своим "целым" числом, оставил как у вас было
    yy = Cells(i, 2)
    End if


    End If
    i = i + 1


Название: Re:Цикл для функции y=x*0.2+x
Отправлено: Дмитрий Щербаков(The_Prist) от 23.01.2019, 10:24:59
не будет же он после 1/100 , делить 2/100 и т.п. до 300
будет. изучайте циклы. Именно сначала 1, потом 2, потом 3 и так до 300 или пока условие не выполнится. Здесь Вас азам обучать никто не будет.

тут мне кажется программа будет выделять именно целое число, так?
именно это я написал постом выше и специально выделил.
(повторюсь), нужно именно условно "целое"
это надо было объяснять и показывать в самом начале. Пример из первого Вашего сообщения говорит ровно об обратном, а именно об использовании реально целого, а не какого-то другого.
каша какая то получилась
да. И притом очень не рабочая, ибо я привел Вам рабочий цикл с правильной проверкой. Осталось только понять какое целое для Вас целое и при каком условии число считать таковым.
после округления не даст ничего кроме нулей, до 2х знаков после запятой
То до 2-х, то до 4-х...А если у число более 4-х знаков после запятой будет в результате вычисления? В общем есть функция Round - изучайте. Она округляет по общепринятым законам. проверяйте через неё вместо Int:
Код: (vb)
If Round(yy,2) = yy Then


А вообще пока не сформулируете нормально и вменяемо то, что есть и что именно надо с нормальным примером - ответа точно не будет. Я уже потерял интерес к теме, т.к. Вы ничего не зная про циклы и их работу пытаетесь рассказать, что предложенный работает не так.
И еще: совершенно не нашел связи приложенной картинки с описанием. Где тут шаг в 0,01 вообще? И на форуме принято не картинки прикладывать, а реальные файлы с данными. Сидеть и перерисовывать то, что у Вас есть в готовом виде никто здесь не захочет.


Название: Re:Цикл для функции y=x*0.2+x
Отправлено: Игорюша от 25.01.2019, 09:04:56
Доброго времени суток.
Переделал немножко, упростил себе задачу.
Получилась вот такая "штуковина":

Код: (vb)
Sub test2()
Dim i As Integer, a As Double
i = 1
  Do While Cells(i, 1) <> ""
  
    Cells(i, 2) = Cells(i, 1) * 0.2 + Cells(i, 1)
    
    If Int(Cells(i, 2)) = Cells(i, 2) Then
    
    Else
    Cells(i, 1) = Cells(i, 1) + 0.01
    ' Как вот на этом месте, совершить "прыжок"
    ' обратно к условию "If Int(Cells(i, 2)) = Cells(i, 2) Then" ?
    ' для того что бы опять произошла проверка.
    End If
    i = i + 1
  
  Loop
 
End Sub

Комментарий администратора Коды оформляйте тегами VBCode. п.п. 4.25 Правил форума (http://www.excel-vba.ru/forum/index.php?topic=2.0)


Название: Re:Цикл для функции y=x*0.2+x
Отправлено: Дмитрий Щербаков(The_Prist) от 25.01.2019, 09:33:01
Игорюша, прочтите правила форума наконец. Обратите внимание как оформлены коды у меня и как у Вас. В правилах об этом написано четко и доступно. Делать это за Вас каждый раз я не буду :)
Как вот на этом месте, совершить "прыжок"
уже хоть где-то про циклы прочитайте в конце-то концов. Они как раз для таких вещей предназначены. Они сами "прыгают" в начало условия, если правильно написаны. А сейчас Ваш код выглядит как некий бред, потому что Вы циклом идете по ячейкам и к каждой из них прибавляете 0,01. При этом ячейка каждый раз разная. Т.е. прибавляете 0,01 к одной ячейке, а проверку потом делаете в другой. В чем смысл - непонятно...


Название: Re:Цикл для функции y=x*0.2+x
Отправлено: Игорюша от 25.01.2019, 10:38:47
Цитировать
Вы циклом идете по ячейкам и к каждой из них прибавляете 0,01. При этом ячейка каждый раз разная. Т.е. прибавляете 0,01 к одной ячейке, а проверку потом делаете в другой


1)Начинается с цикла, который идёт по столбцу(пока не попрут пустые ячейки).
2)На каждой ячейке(1го столбца) сначала выполняется вычисление по формуле: y=x*0.2+x
И записывается каждое полученное значение в соседнюю ячейку(т.е. во второй столбец).
3)Выполняется проверка: Является ли полученное число во второй ячейке целым.
  Если да, то пропускаем и идём "на выход".

А вот как по моему замыслу должно было работать условие "если число из 2й ячейки не целое":
  Если нет,
1)прибавляем +0.01 к числу именно из 1й ячейки(а не из 2й)
2)сделать снова вычисление по формуле y=x*0.2+x,
3)получив новое число для 2й ячейки , снова его проверить на "целое"
 И так, до тех пор пока с помощью прибавлений к первой ячеки, я не получу целое число во второй)

Пойду читать про циклы.


Название: Re:Цикл для функции y=x*0.2+x
Отправлено: Игорюша от 25.01.2019, 10:41:48
То же самое, только с комментариями в коде, и просто попробовать VBcode на форуме.
Код: (vb)
Sub test2()
Dim i As Integer, a As Double
i = 1
  Do While Cells(i, 1) <> ""  ' цикл, идёт по всем ячейкам до "пустых".
  
    Cells(i, 2) = Cells(i, 1) * 0.2 + Cells(i, 1)  ' 1) На каждой ячейке сначала выполняется вычисление по формуле: y=x*0.2+x
     ' И записывается каждое полученное значение в соседнюю ячейку.
    
    If Int(Cells(i, 2)) = Cells(i, 2) Then  ' 2) Выполняется проверка: Является ли полученное число во второй ячейке целым.
    'Если да, то пропускаем и идём "на выход".
    Else
    Cells(i, 1) = Cells(i, 1) + 0.01 'Если нет, то прибавляем +0.01 к числу именно из 1й ячейки.
    ' а вот как "зациклить" условие я ещё не понял.
    End If
    i = i + 1
  
  Loop
 
End Sub


Название: Re:Цикл для функции y=x*0.2+x
Отправлено: Игорюша от 25.01.2019, 12:07:03
Ересь какая то , жаль нельзя свои сообщения удалять.
Пересмотрел код, правда...бред какой то))
    
    


Название: Re:Цикл для функции y=x*0.2+x
Отправлено: Игорюша от 28.01.2019, 09:32:05
Пришлось через GoTo делать(
И то, коряво получается:
Если в столбце 1, поставить в ячейки числа: 17.49 и 17.48
1)Цикл нормально пройдётся по 17.49, сделает вычисление, получит нецелое число во второй ячейке(второй столбец).
2)Проверка выявит, что число во второй ячейке не целое, прибавит 0.01, повторно вычислит функцию, сделает ещё раз проверку проверку на целое число(21) и пойдёт дальше(Line2).

А вот на 17.48(следующая строка) зацикливается, когда к 17.48 два раза прибавится по 0.01 будет 17.5 и при вычислении получится целое число 21, по условию на этом месте нужно выходить на следующую ячейку, но проверка почему то проскакивает опять на Else и снова идут вычисления по этой же ячейке.

В чём тут проблема? В первом же случает прог-ма догадывается 2 раза сделать проверку, почему в 3й раз она не происходит?

Код: (vb)
Sub test2()
Dim i As Integer, a As Double
i = 1
  Do While Cells(i, 1) <> ""
 
    Cells(i, 2) = Cells(i, 1) * 0.2 + Cells(i, 1)
Line1:
    If Int(Cells(i, 2)) = Cells(i, 2) Then
     GoTo Line2
    Else
    Cells(i, 1) = Cells(i, 1) + 0.01
    Cells(i, 2) = Cells(i, 1) * 0.2 + Cells(i, 1)
    GoTo Line1
Line2:
    End If
    i = i + 1
 
  Loop
 
End Sub


Название: Re:Цикл для функции y=x*0.2+x
Отправлено: Дмитрий Щербаков(The_Prist) от 28.01.2019, 19:09:06
Пока Вы наконец не приложите пример файла в Excel - помогать смысла и желания нет.


Название: Re:Цикл для функции y=x*0.2+x
Отправлено: Игорюша от 29.01.2019, 04:28:04
Файлик с расширением .xlsm


Название: Re:Цикл для функции y=x*0.2+x
Отправлено: Игорюша от 29.01.2019, 11:15:02
Или вот, через Until сделал, но то же самое получается(
Код: (vb)
Sub test2()
Dim i As Integer
i = 1
 Do While Cells(i, 1) <> ""
 Cells(i, 2) = Cells(i, 1) * 0.2 + Cells(i, 1)
    Do Until Int(Cells(i, 2)) = Cells(i, 2)
    Cells(i, 1) = Cells(i, 1) + 0.01
    Cells(i, 2) = Cells(i, 1) * 0.2 + Cells(i, 1)
    Loop
    i = i + 1
  Loop
 
End Sub


Название: Re:Цикл для функции y=x*0.2+x
Отправлено: Дмитрий Щербаков(The_Prist) от 29.01.2019, 16:04:52
Не знаю какая закладывается логика записи в ячейку, но вот так должен выглядеть код:
Код: (vb)
Sub test2()
    Dim i As Long, llastr As Long
    llastr = Cells(Rows.Count, 1).End(xlUp).Row 'определяем последнюю ячейку данных
    'цикл от первой ячейки до конца данных
    For i = 1 To llastr
        Do While (Int(Cells(i, 2).Value) <> Cells(i, 2).Value) Or Cells(i, 2).Value = ""
            Cells(i, 1).Value = Cells(i, 1).Value + 0.01
            Cells(i, 2).Value = Cells(i, 1).Value * 0.2 + Cells(i, 1).Value
            DoEvents
        Loop
    Next
End Sub


Название: Re:Цикл для функции y=x*0.2+x
Отправлено: Дмитрий Щербаков(The_Prist) от 29.01.2019, 16:40:41
Еще лучше сделать так:
Код: (vb)
Sub test2()
    Dim i As Long, llastr As Long
    Dim d1 As Double, d2 As Double
    llastr = Cells(Rows.Count, 1).End(xlUp).Row
    For i = 1 To llastr
        d1 = Cells(i, 1).Value
        d2 = d1 * 0.2 + d1
        Do While Round(Int(d2), 4) <> Round(d2, 4) ' Or Cells(i, 2).Value = ""
            d1 = d1 + 0.01
            d2 = d1 * 0.2 + d1
            If d2 > 100000 Then
                'принудительно завершаем цикл
                'если число уже вышло за рамки, а решение не найдено
                d2 = 0
                d1 = 0
                Exit Do
            End If
            DoEvents
        Loop
        'записываем конечное значение для второго столбца
        Cells(i, 2).Value = d2
        'записываем конечное значение для первого столбца(для проверки в третий)
        Cells(i, 3).Value = d1
    Next
End Sub

потому что
1. У числа d2 могут появляться "невидимые" хвосты в 15-значащем разряде после запятой, что приведет к ложному неравенству
2. Есть условие выхода из цикла при недостижении цели после определенного порогового значения. И такое тоже может быть. Тогда запишутся просто нули.
3. Этот код работать будет значительно быстрее


Название: Re:Цикл для функции y=x*0.2+x
Отправлено: Игорюша от 30.01.2019, 09:29:47
Ещё раз спасибо, за помощь)
Записывал значения в ячейку, что бы проверять их пошагово.

Вопрос по условию:
Код: (vb)
(Do While Round(Int(d2), 4) <> Round(d2, 4)

"Делать пока округлённое целое d2, неравно округлённому d2"
Оно так читается ?


Добавил немножко: d2 = Round(d2, 4)
А то получалось вот так:
Число 424.88(d1), по условию уже на 425(d1) должно выдать  ровно 510(d2).
получалось что оно проскакивает  до 2541.50(d2) и 2117.50(d1).
Хотя это может быть менее точное значение.

Сейчас вроде бы работает как нужно)
Код: (vb)
    Sub test3()
        Dim i As Long, llastr As Long
        Dim d1 As Double, d2 As Double
        llastr = Cells(Rows.Count, 1).End(xlUp).Row
        For i = 1 To llastr
            d1 = Cells(i, 1).Value
            d2 = d1 * 0.2 + d1
            d2 = Round(d2, 4) ' Добавил вот тут
            Do While Round(Int(d2), 4) <> Round(d2, 4) ' Or Cells(i, 2).Value = ""
                d1 = d1 + 0.01
                d2 = d1 * 0.2 + d1
                d2 = Round(d2, 4) ' И тут
                If d2 > 10000 Then
                  
                    d2 = 0
                    d1 = 0
                    Exit Do
                End If
                DoEvents
            Loop
            
            Cells(i, 2).Value = d2
            Cells(i, 3).Value = d1
        Next
    End Sub