Erster Stand: Matrixberechnungen und Projektstruktur
This commit is contained in:
commit
2019d5897c
4 files changed
+124
No files matched your search
@@ -0,0 +1,4 @@
|
|||||||
|
.venv/
|
||||||
|
__pycache__/
|
||||||
|
.env
|
||||||
|
.ruff_cache/
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# Regeln für dieses Projekt
|
||||||
|
- Code nach PEP 8, Zeilenlänge maximal 88 Zeichen.
|
||||||
|
- Jede Funktion und Methode hat einen Docstring und Type Hints.
|
||||||
|
- Vor jedem Commit: `ruff check` und `ruff format`.
|
||||||
+109
@@ -0,0 +1,109 @@
|
|||||||
|
"""Matrixberechnungen."""
|
||||||
|
|
||||||
|
from math import cos, isclose, radians, sin
|
||||||
|
|
||||||
|
Matrix = list[list[int | float]]
|
||||||
|
|
||||||
|
|
||||||
|
def validate_matrix(matrix: Matrix, name: str = "matrix") -> tuple[int, int]:
|
||||||
|
"""Prüfe eine Matrix und liefere ihre Zeilen- und Spaltenzahl.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
TypeError: Bei falschen Containertypen oder Einträgen, die keine
|
||||||
|
int- oder float-Werte sind, einschließlich bool.
|
||||||
|
ValueError: Bei leeren Matrizen, leeren Zeilen oder
|
||||||
|
unterschiedlich langen Zeilen.
|
||||||
|
"""
|
||||||
|
if not isinstance(matrix, list):
|
||||||
|
raise TypeError(f"{name} muss eine Liste von Listen sein.")
|
||||||
|
if not matrix:
|
||||||
|
raise ValueError(f"{name} darf nicht leer sein.")
|
||||||
|
if any(not isinstance(row, list) for row in matrix):
|
||||||
|
raise TypeError(f"Jede Zeile von {name} muss eine Liste sein.")
|
||||||
|
|
||||||
|
columns = len(matrix[0])
|
||||||
|
if columns == 0:
|
||||||
|
raise ValueError(f"{name} darf keine leeren Zeilen enthalten.")
|
||||||
|
if any(len(row) != columns for row in matrix):
|
||||||
|
raise ValueError(f"{name} muss rechteckig sein.")
|
||||||
|
if any(
|
||||||
|
isinstance(value, bool) or not isinstance(value, (int, float))
|
||||||
|
for row in matrix
|
||||||
|
for value in row
|
||||||
|
):
|
||||||
|
raise TypeError(
|
||||||
|
f"Alle Einträge von {name} müssen int oder float sein, ohne bool."
|
||||||
|
)
|
||||||
|
|
||||||
|
return len(matrix), columns
|
||||||
|
|
||||||
|
|
||||||
|
def matmul(left: Matrix, right: Matrix) -> Matrix:
|
||||||
|
"""Multipliziere zwei Matrizen mit passenden Dimensionen."""
|
||||||
|
_, left_columns = validate_matrix(left, "left")
|
||||||
|
right_rows, right_columns = validate_matrix(right, "right")
|
||||||
|
if left_columns != right_rows:
|
||||||
|
raise ValueError(
|
||||||
|
"Die Spaltenzahl von left muss der Zeilenzahl von right entsprechen "
|
||||||
|
f"({left_columns} != {right_rows})."
|
||||||
|
)
|
||||||
|
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
sum(left_row[index] * right[index][column] for index in range(left_columns))
|
||||||
|
for column in range(right_columns)
|
||||||
|
]
|
||||||
|
for left_row in left
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def transpose(matrix: Matrix) -> Matrix:
|
||||||
|
"""Vertausche die Zeilen und Spalten einer Matrix."""
|
||||||
|
_, column_count = validate_matrix(matrix)
|
||||||
|
return [[row[column] for row in matrix] for column in range(column_count)]
|
||||||
|
|
||||||
|
|
||||||
|
def rot_2D(angle: float) -> Matrix:
|
||||||
|
"""Erzeuge eine zweidimensionale Rotationsmatrix zum Winkel im Bogenmaß."""
|
||||||
|
return [
|
||||||
|
[cos(angle), -sin(angle)],
|
||||||
|
[sin(angle), cos(angle)],
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
integer_product = matmul([[1, 2], [3, 4]], [[5, 6], [7, 8]])
|
||||||
|
assert integer_product == [[19, 22], [43, 50]]
|
||||||
|
print("Beispiel 1:", integer_product)
|
||||||
|
|
||||||
|
rectangular_product = matmul(
|
||||||
|
[[1, 2, 3], [4, 5, 6]],
|
||||||
|
[[7, 8], [9, 10], [11, 12]],
|
||||||
|
)
|
||||||
|
assert rectangular_product == [[58, 64], [139, 154]]
|
||||||
|
print("Beispiel 2:", rectangular_product)
|
||||||
|
|
||||||
|
float_product = matmul([[0.5, 1.5]], [[2.0], [4.0]])
|
||||||
|
assert float_product == [[7.0]]
|
||||||
|
print("Beispiel 3:", float_product)
|
||||||
|
|
||||||
|
transposed_matrix = transpose([[1, 2, 3], [4, 5, 6]])
|
||||||
|
assert transposed_matrix == [[1, 4], [2, 5], [3, 6]]
|
||||||
|
print("Transponiert:", transposed_matrix)
|
||||||
|
|
||||||
|
rotated_point = matmul(rot_2D(radians(90)), [[1], [0]])
|
||||||
|
assert isclose(rotated_point[0][0], 0, abs_tol=1e-9)
|
||||||
|
assert isclose(rotated_point[1][0], 1, abs_tol=1e-9)
|
||||||
|
print("Rotation um 90°:", rotated_point)
|
||||||
|
|
||||||
|
clockwise_point = matmul(rot_2D(radians(-90)), [[0], [1]])
|
||||||
|
assert isclose(clockwise_point[0][0], 1, abs_tol=1e-9)
|
||||||
|
assert isclose(clockwise_point[1][0], 0, abs_tol=1e-9)
|
||||||
|
print("Rotation um -90°:", clockwise_point)
|
||||||
|
|
||||||
|
try:
|
||||||
|
matmul([[1, 2]], [[3, 4]])
|
||||||
|
except ValueError:
|
||||||
|
print("Nicht passende Dimensionen: ValueError wie erwartet.")
|
||||||
|
else:
|
||||||
|
raise AssertionError("Bei nicht passenden Dimensionen fehlt der ValueError.")
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
[project]
|
||||||
|
name = "matrixmania"
|
||||||
|
version = "0.1.0"
|
||||||
|
requires-python = ">=3.10"
|
||||||
|
|
||||||
|
[tool.ruff]
|
||||||
|
line-length = 88
|
||||||
Reference in new issue
Block a user