Аппроксимация методом наименьших квадратов на базе полиномов Эрмита на Haskell
.pdf
putStrLn "\nСохранить результаты в файл? (y/...)" save <- getLine
when (save == "y" || save == "Y") $ do
putStrLn "Введите имя файла для сохранения:" outFile <- getLine
writeResultsToFile outFile points coefs m
putStrLn "\nАппроксимация завершена успешно!"
--Основная функция
--Основная функция
main :: IO () main = do
hSetBuffering stdout NoBuffering putStrLn $ replicate 60 '='
putStrLn "АППРОКСИМАЦИЯ МЕТОДОМ НАИМЕНЬШИХ КВАДРАТОВ" putStrLn "в базисе полиномов Эрмита"
putStrLn $ replicate 60 '='
-- Получаем валидный путь к файлу с проверкой существования file <- requestFilePath
-- Теперь читаем точки с обработкой возможных ошибок чтения points <- catch (readPoints file)
(\(e :: SomeException) -> do
putStrLn $ "ОШИБКА при чтении файла: " ++ show e putStrLn "Программа завершена."
return [])
if null points || length points < 2 then do
putStrLn "Ошибка: недостаточно точек для аппроксимации!" putStrLn "Необходимо как минимум 2 точки."
21
else do
let numPoints = length points
minX = minimum [x | (x, _, _) <- points] maxX = maximum [x | (x, _, _) <- points]
putStrLn $ printf "\nДиапазон x: [%.3f, %.3f]" minX maxX putStrLn $ "Количество точек: " ++ show numPoints
putStrLn $ "Максимально допустимая степень полинома: 10" putStrLn "\nВведите степень полинома Эрмита m (целое):" mStr <- getLine
let mMaybe = readMaybe mStr :: Maybe Int case mMaybe of
Nothing -> do
putStrLn "Ошибка ввода: введите целое число"
putStrLn "Установлена степень 0 (аппроксимация константой)" runApproximation points 0 minX maxX
Just m -> do
-- Простая коррекция с отдельными проверками let correctedM
| m < 0 = 0
| m > 10 = 10
| otherwise = m
-- Выводим предупреждения о коррекции when (m < 0) $
putStrLn $ "Предупреждение: отрицательная степень " ++ show m ++ " установлена в 0"
when (m > 10) $ do
putStrLn $ "Предупреждение: степень " ++ show m ++ " превышает максимальную: 10" putStrLn $ "Установлена максимальная степень: 10"
-- Дополнительные предупреждения
22
when (correctedM == 0) $
putStrLn "Аппроксимация полиномом нулевой степени (константа)"
when (correctedM > numPoints `div` 2) $
putStrLn "Предупреждение: высокая степень полинома может привести к переобучению"
runApproximation points correctedM minX maxX
Тестирование
Для проверки работоспособности программы были выполнены тестовые запуски.
Первый тест:
Рисунок 3. Результат теста для первого набора данных |
||||||||
60 |
|
|
|
|
|
|
|
|
50 |
|
|
|
|
|
|
|
|
40 |
|
|
|
|
|
|
|
|
30 |
|
|
|
|
|
|
|
|
20 |
|
|
|
|
|
|
|
|
10 |
|
|
|
|
|
|
|
|
0 |
|
|
|
|
|
|
|
|
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
|
|
Без аппрокс. |
|
Аппрокс. |
|
|
||
Рисунок 4. Графики результата теста для первого набора данных |
||||||||
23
Второй тест:
|
Рисунок 5. Результат теста для второго набора данных |
|
||||
7 |
|
|
|
|
|
|
6 |
|
|
|
|
|
|
5 |
|
|
|
|
|
|
4 |
|
|
|
|
|
|
3 |
|
|
|
|
|
|
2 |
|
|
|
|
|
|
1 |
|
|
|
|
|
|
0 |
|
|
|
|
|
|
1 |
2 |
3 |
4 |
5 |
6 |
7 |
|
|
Без аппрокс. |
Аппрокс. |
|
|
|
|
Рисунок 6. Графики результата теста для второго набора данных |
|
||||
24
Третий тест:
|
|
Рисунок 7. Результат теста для третьего набора данных |
|||
14 |
|
|
|
|
|
12 |
|
|
|
|
|
10 |
|
|
|
|
|
8 |
|
|
|
|
|
6 |
|
|
|
|
|
4 |
|
|
|
|
|
2 |
|
|
|
|
|
0 |
|
|
|
|
|
1 |
3 |
5 |
7 |
9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 |
|
|
|
|
|
Без аппрокс. |
Аппрокс. |
Рисунок 8. Графики результата теста для третьего набора данных |
|||||
Заключение
В ходе лабораторной работы была разработана программа аппроксимации методом наименьших квадратов на базе полиномов Эрмита на языке программирования Haskell.
25
