Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Р3212/medvedev_409111/lab1/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module Lab_1

go 1.23
191 changes: 191 additions & 0 deletions Р3212/medvedev_409111/lab1/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
package main

import (
matrix2 "Lab_1/matrix"
"bufio"
"fmt"
"math/rand"
"os"
"strconv"
"strings"
"time"
)

func main() {
var size, maxIter int
var accuracy float64
var isFile bool
var isRandom bool
reader, file, readerErr := getReader()
if file != nil {
defer file.Close()
isFile = true
} else {
isFile = false
}
if readerErr != nil {
fmt.Println(readerErr.Error())
return
}
var line string
var splitline []string
if !isFile {
fmt.Print("Введите размер матрицы: ")
}
line, err := reader.ReadString('\n')
if err != nil {
fmt.Println(err.Error())
return
}
size, err = strconv.Atoi(strings.TrimSpace(line))
if err != nil {
fmt.Println(err.Error())
}
data := make([][]float64, size)
vecB := make([]float64, size)
if !isFile {
fmt.Print("Введите любой символ если хотите заполнить матрицу случайными числами: ")
line, err = reader.ReadString('\n')
line = line[:len(line)-1]
if line != "" {
rand.Seed(time.Now().UnixNano())
for i := 0; i < size; i++ {
data[i] = make([]float64, size)
for j := 0; j < size; j++ {
data[i][j] = rand.Float64() * 100
}
}
for i := 0; i < size; i++ {
vecB[i] = rand.Float64()
}
isRandom = true
} else {
isRandom = false
}
}
if !isRandom {
if !isFile {
fmt.Println("Введите матрицу:")
}
for i := 0; i < size; i++ {
data[i] = make([]float64, size)
line, err = reader.ReadString('\n')
if err != nil {
fmt.Println(err.Error())
return
}
splitline = strings.Split(strings.TrimSpace(line), " ")
if len(splitline) != size {
fmt.Printf("Длина %d строки матрицы некорректна\n", i+1)
}
for j := 0; j < size; j++ {
data[i][j], err = strconv.ParseFloat(splitline[j], 64)
if err != nil {
fmt.Println(err.Error())
return
}
}
}
if !isFile {
fmt.Println("Введите вектор b: ")
}
line, err = reader.ReadString('\n')
if err != nil {
fmt.Println(err.Error())
return
}
splitline = strings.Split(strings.TrimSpace(line), " ")
if len(splitline) != size {
fmt.Println("Некорректное количество элементов для вектора b")
return
}
for i := 0; i < size; i++ {
vecB[i], err = strconv.ParseFloat(splitline[i], 64)
if err != nil {
fmt.Println(err.Error())
return
}
}
}
if !isFile {
fmt.Print("Введите максимальное количество итераций: ")
}
line, err = reader.ReadString('\n')
if err != nil {
fmt.Println(err.Error())
return
}
maxIter, err = strconv.Atoi(strings.TrimSpace(line))
if err != nil {
fmt.Println(err.Error())
return
}
if !isFile {
fmt.Print("Введите точность: ")
}
line, err = reader.ReadString('\n')
if err != nil {
fmt.Println(err.Error())
return
}
accuracy, err = strconv.ParseFloat(strings.TrimSpace(line), 64)
if err != nil {
fmt.Println(err.Error())
return
}
matrix := matrix2.BuildMatrix(size, maxIter, data, vecB, accuracy)
if isRandom {
fmt.Println("Сгенерированная матрица: ")
fmt.Println(matrix.StringMatrix())
}
if matrix.MakeDiagonallyDominant() {
fmt.Println("Диагональное преобразование найдено:")
fmt.Println(matrix.StringMatrix())
} else {
fmt.Println("Диагональное преобразование невозможно")
}
fmt.Printf("Норма матрицы: %f\n", matrix.Norm())
x, iter, errors, err := matrix.GaussSeidel()
if err != nil {
fmt.Println(err.Error())
fmt.Println("Отклонения: ")
for i := 0; i < size; i++ {
fmt.Println(errors[i])
}
return
}
fmt.Printf("Решено за %d итераций\n", iter)
fmt.Println("Отклонения: ")
for i := 0; i < size; i++ {
fmt.Println(errors[i])
}
fmt.Println("Решение: ")
for i := 0; i < size; i++ {
fmt.Println(x[i])
}
}

func getReader() (*bufio.Reader, *os.File, error) {
var line string
stdin := bufio.NewReader(os.Stdin)
fmt.Print("Введите любой символ, если хотите ввести данные из файла: ")
line, err := stdin.ReadString('\n')
line = line[:len(line)-1]
if err != nil {
return nil, nil, err
}
if line == "" {
return bufio.NewReader(stdin), nil, nil
}
fmt.Print("Введите название файла: ")
line, err = stdin.ReadString('\n')
line = line[:len(line)-1]
if err != nil {
return nil, nil, err
}
file, err := os.Open(line)
if err != nil {
return nil, nil, err
}
return bufio.NewReader(file), file, nil
}
110 changes: 110 additions & 0 deletions Р3212/medvedev_409111/lab1/matrix/matrix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package matrix

import (
"fmt"
"math"
)

type Matrix struct {
size, maxIter int
data [][]float64
vecB []float64
accuracy float64
}

func BuildMatrix(size, maxIter int, data [][]float64, vecB []float64, accuracy float64) *Matrix {
matrix := &Matrix{size, maxIter, data, vecB, accuracy}
return matrix
}

func (matrix *Matrix) IsDiagonallyDominant() bool {
for i := 0; i < matrix.size; i++ {
sum := 0.0
for j := 0; j < matrix.size; j++ {
if i != j {
sum += math.Abs(matrix.data[i][j])
}
}
if math.Abs(matrix.data[i][i]) <= sum {
return false
}
}
return true
}

func (matrix *Matrix) MakeDiagonallyDominant() bool {
for i := 0; i < matrix.size; i++ {
maxRow := i
maxVal := math.Abs(matrix.data[i][i])
for k := i + 1; k < matrix.size; k++ {
if math.Abs(matrix.data[k][i]) > maxVal {
maxVal = math.Abs(matrix.data[k][i])
maxRow = k
}
}
if maxRow != i {
matrix.data[i], matrix.data[maxRow] = matrix.data[maxRow], matrix.data[i]
matrix.vecB[i], matrix.vecB[maxRow] = matrix.vecB[maxRow], matrix.vecB[i]
}
}
if matrix.IsDiagonallyDominant() {
return true
} else {
return false
}
}

func (matrix *Matrix) StringMatrix() string {
ans := ""
for i := 0; i < matrix.size; i++ {
for j := 0; j < matrix.size; j++ {
ans += fmt.Sprintf("%v", matrix.data[i][j]) + " "
}
ans += fmt.Sprintf("%v", matrix.vecB[i]) + string('\n')
}
return ans[:len(ans)-1]
}

func (matrix *Matrix) GaussSeidel() ([]float64, int, []float64, error) {
x := make([]float64, matrix.size)
for idx, _ := range x {
x[idx] = matrix.vecB[idx] / matrix.data[idx][idx]
}
errors := make([]float64, matrix.size)

for iter := 0; iter < matrix.maxIter; iter++ {
maxDiff := 0.0
for i := 0; i < matrix.size; i++ {
sum := 0.0
for j := 0; j < matrix.size; j++ {
if j != i {
sum += matrix.data[i][j] * x[j]
}
}
newX := float64(matrix.vecB[i]-sum) / float64(matrix.data[i][i])
errors[i] = math.Abs(newX - x[i])
if errors[i] > maxDiff {
maxDiff = errors[i]
}
x[i] = newX
}
if maxDiff <= matrix.accuracy {
return x, iter + 1, errors, nil
}
}
return nil, matrix.maxIter, errors, fmt.Errorf("Решения за %d итераций при указанной точности не найдено\n", matrix.maxIter)
}

func (matrix *Matrix) Norm() float64 {
maxNorm := 0.0
for _, row := range matrix.data {
sum := 0.0
for _, val := range row {
sum += math.Abs(val)
}
if sum > maxNorm {
maxNorm = sum
}
}
return maxNorm
}
Binary file not shown.
Binary file not shown.
Loading