Skip to content

Файлы и математические расчёты функции

Доброго времени суток. Сегодня мы разберём достаточно сложную задачу, которая охватывает несколько пройденных с вами тем ( Работа с файлами и Работа с математическими функциями)

Сама задача состоит в том, чтобы написать программу, которая производит необходимый расчёт функции по данным, введёнными пользователем, и записывает результаты в файл со штампом в начале файла ( » Функция : y = e ^ x, количество точек по х и у и т.д. «). Следует учесть возможность ввести несколько интервалов расчётов.

Также программа должна выводить отчёт о своей работе в файл Output.dat, где должна быть указанна функция, с которой производились операции, количество интервалов введённых пользователем и имена файлов, которые содержат расчёты по тому или иному интервалу. В программе должна быть учтена возможность возникновения ошибки при расчётах и вывод этих ошибок в файл отчёта Output.dat.

Функция от двух переменных в формате G(x, y)=y*F(x), F(x) = где lg(x–5). В случае у принять начальное значение 5, шаг = 0,5 и количество точек 10.

Страшно? Можно сказать, что это уже реальная и практическая задача, которую вам могут дать.
Разбор полётов будет совершаться малыми блоками и не по порядку ( как в исходнике). Это необходимо для наилучшего понимания. Сам исходник, как и раньше, прилагается в конце статьи.
Начнём с того, откуда будем брать данные. Я предлагаю такой формат:
Снимок7
Где x1 — начало интервала, x2 — конец и n — количество точек.

Dim x1() As Double
Dim x2() As Double
Dim nx() As Double
Dim count As Integer
Dim i As Integer
'_________________________________считывание
count = 1
i = 1
Do While count <> 0
    If Cells(i + 1, 1) <> "" Then
        ReDim Preserve x1(i) As Double
        ReDim Preserve x2(i) As Double
        ReDim Preserve nx(i) As Double
        x1(i - 1) = Cells(i + 1, 1)
        x2(i - 1) = Cells(i + 1, 2)
        nx(i - 1) = Cells(i + 1, 3) 
        i = i + 1
    Else: count = 0
    End If
Loop

Пока не попадётся пустая ячейка, мы будем считывать данные и записывать их в соответствующие массивы. Напомню, что Redim Preserve … изменяет размер массива без потери данных внутри него.

'_________________________________расчёт по y
Dim n As Integer
Dim YN As Integer
YN = 10
Dim y() As Double
ReDim y(YN) As Double
Dim hy As Double
n = 5
hy = 0.5
Dim j As Integer
y(0) = n
For j = 1 To YN - 1
    y(j) = y(j - 1) + hy
Next j

Тут несложные действия по расчёту массива y.

ChDir ("C:......\vba\files")
Dim fil As Integer
Dim files() As String
ReDim files(i - 1) As String
For fil = 1 To i - 1
    files(fil - 1) = "G" + CStr(fil) + ".dat"
Next fil

ChDir() — изменят ваше текущее положение в каталогах. По умолчанию вы находитесь там, где открыт файл Excel. В данный момент это необходимо только для удобства, приятнее держать расчётные таблицы отдельно. Не так ли?

Также тут создаём строковый массив, который будет хранить в себе названия расчётных файлов. Переменная i была посчитана в раннее описанном блоке.

Dim stroka_y As String
For j = 0 To 10
    If j = 0 Then
    stroka_y = stroka_y + "x\y" + "     "
    Else: stroka_y = stroka_y + CStr(y(j - 1)) + "         "
    End If
Next j

В данном блоке записывается первая строчка для таблиц. Она везде будет одинаковой. В итоге выглядит она так.
Снимок8
Перед основным блоком напишем математические функции.

Dim erorka As String

Function f(x As Double)
f = Log(x - 5)
End Function
Function G(x As Double, y As Double) As Variant
On Error GoTo errHandler
G = y * f(x)

Exit Function
errHandler:
  MsgBox Err.Description, vbCritical, "Error No: " & Err.Number
G = "NaN"
erorka = erorka + "Ошибка №" + CStr(Err.Number) + "  при x = " + CStr(x) + "  и при у = " + CStr(y) + vbNewLine
Resume Next
End Function

Переменная erorka объявлена глобально, то есть вне всяких процедур и функций (sub и Function). В неё записываются ошибки, возникающие в функции G(). Также при возникновении ошибки, к G приравнивается «NaN». Это возможно, благодаря типу функции as Variant, который может работает как со строками, так и с числами.

При нежелании использовать Variant, советую приравнять G самому минимально возможному в вашем типе числу, а далее сделать отлов этого числа условием и соответствующий вывод в файл.

Теперь главное блюдо:

Dim n_x1 As Double
Dim n_x2 As Double
Dim step As Double
Dim t1 As Integer
Dim t2 As Integer
Dim t3 As Integer
Dim stroka As String
Dim temp As Variant
stroka = ""
For t1 = 1 To i - 1 ' количество интервалов
    n_x1 = x1(t1 - 1)
    n_x2 = x2(t1 - 1)
    step = (n_x2 - n_x1) / nx(t1 - 1)
    Open files(t1 - 1) For Output As #t1
    Print #t1, CStr(nx(t1 - 1)) + " " + CStr(YN) + "  Function: y*lg(x-5)" ' начальная строка файла
    Print #t1, stroka_y ' первая строка таблицы
    For t2 = 1 To nx(t1 - 1) ' количество точек по Х
        stroka = CStr(Round(n_x1, 3)) + "         " ' запись строки для таблицы
        For t3 = 0 To YN - 1 ' количество точек по Y
            temp = G(n_x1, y(t3))
            Cells(2 + t2 + (t1 - 1) * 5, 7 + t3) = temp ' вывод на лист в  excel для проверки
            If t3 <> YN - 1 Then
                If temp <> "NaN" Then
                stroka = stroka + CStr(Round(temp, 3)) + "      "
                Else: stroka = stroka + temp + "      "
                End If
            Else:
                If G(n_x1, y(t3)) <> "NaN" Then
                    stroka = stroka + CStr(Round(temp, 3))
                    Else: stroka = stroka + temp
                End If
          End If
        Next t3
        n_x1 = n_x1 + step
        Print #t1, stroka
    Next t2
    Close #t1
Next t1

Здесь присутствует три цикла: с помощью первого мы проходим по всем интервалам, второго — записываем начальные значения X для таблицы (первый столбец) и третий — уже для записи в строку полученных значений в строку.

Этой командой Open files(t1 — 1) For Output As #t1 мы открываем файл с именем, взятым из массива files и назначаем ему идентификатор #t1. Строка If t3 <> YN — 1 Then проверяет на последний индекс в массиве Y, чтобы корректнее заполнить таблицу. Напомню,что команда Round () округляет значения до указанного количества чисел после запятой.
И последнее, отчёт:

'__________________________________Output.dat

Open "Output.dat" For Output As #1
Print #1, "Name:Example by CodeTown.ru Version:0000000001 beta"
Print #1, "Function: y*lg(x-5)"
Print #1, CStr(i - 1)
For fil = 1 To i - 1
    Print #1, files(fil - 1)
Next fil
Print #1, erorka
Close #1

Выглядеть он будет так:
Снимок9
Сразу скажу, что ошибка допущена специально, для проверки работы обработчика ошибок.
Общий итог ( показано 2 открытых файла расчётов и папка где они лежат ):

На этом мы закончим, молодцы! Если остались вопросы, пишите в комментариях.

Вот исходники, не забудьте прописать путь каталогу в Chdir() или вовсе его стереть.
Скачать исходники

Опубликовано вVBA

Будьте первым, кто оставит комментарий

    Добавить комментарий

    Ваш e-mail не будет опубликован. Обязательные поля помечены *