diff --git a/.github/openSeries.png b/.github/openSeries.png index 47ebfa5..e9dfba4 100644 Binary files a/.github/openSeries.png and b/.github/openSeries.png differ diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 11059d3..54dd7be 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -4,15 +4,6 @@ ## Checklist: -### Umum: - - - -- [ ] Saya menambah fungsi / algoritma. -- [ ] Saya memperbaiki algoritma yang sudah ada. -- [ ] Saya memperbaiki dokumentasi. -- [ ] Saya menambah dokumentasi. - ### Contributor Requirements (Syarat Kontributor) dan Lain-Lain: diff --git a/.gitignore b/.gitignore index dd84ca7..4538086 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,5 @@ next-env.d.ts # cache dari dist dist + +.DS_Store diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1246c29..b048161 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,7 +22,7 @@ repos: # ruff adalah salah satu linter dan formatter kode - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.1.14 + rev: v0.2.0 hooks: - id: ruff - id: ruff-format diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fa5b9fb..b7a6b2b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -144,6 +144,11 @@ kendala atau masalah ketika melakukan pull request. Kamu juga bisa bertanya pada Catatan: pesan commit harus menjelaskan perubahan secara singkat. +jika kamu ingin menjelaskan pesan commit yang panjang kamu bisa menggunakan parameter `-m` +``` +git commit -m "feat: judul perubahan" -m "deskripsi dari perubahan" +``` + Contoh yang benar: - ☒ feat: test_x.py diff --git a/OpenSeries/bilangan_istimewa.py b/OpenSeries/bilangan_istimewa.py new file mode 100644 index 0000000..4261202 --- /dev/null +++ b/OpenSeries/bilangan_istimewa.py @@ -0,0 +1,115 @@ +import OpenSeries.util.error as error +from typing import Union + + +def angka_armstrong(angka: int) -> Union[str, error.ErrorTipeData]: + """ + angka armstrong adalah bilangan bulat positif yang sama dengan jumlah + pangkat tiga dari digit-digitnya + + contoh: + 153 = 1^3 + 5^3 + 3^3 = 153 + + Parameter: + angka(int): angka yang akan di cek + error.ErrorTipeData: jika tipe data yang dimasukkan salah + """ + benar, bukan = "angka armstrong", "bukan angka armstrong" + # cek tipe data dari variable angka + if isinstance(angka, (float, str)): + return error.ErrorTipeData(["int"]) + else: + total = 0 + number_of_digit = 0 + temp = angka + + number_of_digit = len(str(angka)) + temp = angka + while temp > 0: + rem = temp % 10 + total += rem**number_of_digit + temp //= 10 + if angka == total: + return benar.capitalize() + return bukan.capitalize() + + +def angka_automorphic(angka: int) -> Union[str, error.ErrorTipeData]: + """ + angka automorphic adalah bilangan asli dalam basis bilangan tertentu yang kuadratnya + berakhir dengan angka yang sama dengan bilangan itu sendiri + + dalam basis 10, 5 adalah angka automorphic karena 5^2 = 25, dan keduanya diakhiri dengan + angka 5 + dalam basis 2, 110 adalah angka automorphic karena 110^2 = 12100, dan anga diakhiri dengan + digit 0 + + Parameter: + angka (int): mengecek angka tersebut automorphic atau tidak + + Return: + str: mengembalikan informasi jika benar atau bukan + error.ErrorTipeData: jika tipe data yang dimasukkan salah + """ + benar, bukan = "angka automorphic", "bukan angka automorphic" + # cek dari tipe data angka + if not isinstance(angka, int): + return error.ErrorTipeData(["int"]) + if angka < 0: + return bukan.capitalize() + + kuadrat_angka = angka * angka + while angka < 0: + if angka % 10 != kuadrat_angka % 10: + return bukan.capitalize() + angka //= 10 + kuadrat_angka //= 10 + return benar.capitalize() + + +def angka_pronic(angka: int) -> Union[str, error.ErrorTipeData]: + """ + angka pronic adalah bilangan bulat positif yang merupakan hasil perkalian + dari dua bilangan bulat berurutan + 6 = 2 * (2 + 1) = 2 * 3 = 6 + 12 = 3 * (3 + 1) = 3 * 4 = 12 + 20 = 4 * (4 + 1) = 4 * 5 = 20 + + Parameter: + angka(int): angka yang akan di cek + + Return: + str: mengembalikan informasi jika benar atau bukan + error.ErrorTipeData: jika tipe data yang dimasukkan salah + """ + benar, bukan = "angka pronic", "bukan angka pronic" + # cek dari tipe data angka + if not isinstance(angka, int): + return error.ErrorTipeData(["int"]) + if angka < 0 or angka % 2 == 1: + return bukan.capitalize() + angka_pangkat = int(angka**0.5) + return ( + benar.capitalize() + if angka == angka_pangkat * (angka_pangkat + 1) + else bukan.capitalize() + ) + + +def angka_segitiga(angka: int) -> Union[int, error.ErrorTipeData, error.Error]: + """ + bilangan segitiga adalah bilangan yang dapat disusun dalam bentuk segitiga sama sisi + + Parameter: + angka (int): angka yang ingin dimasukkan + + Return: + int: angka segitiga di posisi yang ditentukan + error.Error: jika angka negatif + error.ErrorTipeData: jika tipe data salah + """ + if not isinstance(angka, int): + return error.ErrorTipeData(["int"]) + if angka < 0: + return error.Error("angka tidak boleh negatif") + return angka * (angka + 1) // 2 diff --git a/OpenSeries/matematika.py b/OpenSeries/matematika.py index aedec54..a0fcd07 100644 --- a/OpenSeries/matematika.py +++ b/OpenSeries/matematika.py @@ -1,6 +1,6 @@ from OpenSeries.util import constant as constant from OpenSeries.util import error as error -from typing import Union, Sequence +from typing import Union, Sequence, Callable import numpy as np import math @@ -21,7 +21,7 @@ def radian_ke_derajat(radian: Union[float, int]) -> Union[float, error.ErrorTipe if not isinstance(radian, (float, int)): return error.ErrorTipeData(["float", "int"]) else: - return radian * (180 / constant.pi) + return radian * (180 / constant.PI) def derajat_ke_radian(derajat: Union[float, int]) -> Union[float, error.ErrorTipeData]: @@ -40,7 +40,7 @@ def derajat_ke_radian(derajat: Union[float, int]) -> Union[float, error.ErrorTip if not isinstance(derajat, (float, int)): return error.ErrorTipeData(["float", "int"]) else: - return derajat * (constant.pi / 180) + return derajat * (constant.PI / 180) def radian_ke_gradian(radian: Union[float, int]) -> Union[float, error.ErrorTipeData]: @@ -59,7 +59,7 @@ def radian_ke_gradian(radian: Union[float, int]) -> Union[float, error.ErrorTipe if not isinstance(radian, (float, int)): return error.ErrorTipeData(["float", "int"]) else: - return radian * (200 / constant.pi) + return radian * (200 / constant.PI) def gradian_ke_radian(gradian: Union[float, int]) -> Union[float, error.ErrorTipeData]: @@ -78,7 +78,7 @@ def gradian_ke_radian(gradian: Union[float, int]) -> Union[float, error.ErrorTip if not isinstance(gradian, (float, int)): return error.ErrorTipeData(["float", "int"]) else: - return gradian * (constant.pi / 200) + return gradian * (constant.PI / 200) def luas_lingkaran(jari: Union[float, int]) -> Union[float, error.ErrorTipeData]: @@ -95,7 +95,7 @@ def luas_lingkaran(jari: Union[float, int]) -> Union[float, error.ErrorTipeData] # mengecek apakah variable tersebut bertipe data int atau float # jika tidak maka error if isinstance(jari, (float, int)): - return constant.pi * jari**2 + return constant.PI * jari**2 else: return error.ErrorTipeData(["float", "int"]) @@ -113,7 +113,7 @@ def keliling_lingkaran(jari: Union[float, int]) -> Union[float, error.ErrorTipeD # mengecek apakah variable tersebut bertipe data int atau float # jika tidak maka error if isinstance(jari, (float, int)): - return 2 * constant.pi * jari + return 2 * constant.PI * jari else: return error.ErrorTipeData(["float", "int"]) @@ -131,10 +131,9 @@ def diameter_lingkaran(jari: Union[float, int]) -> Union[float, error.ErrorTipeD """ # mengecek apakah variable tersebut bertipe data int atau float # jika tidak maka error - if isinstance(jari, (float, int)): - return 2 * jari - else: + if not isinstance(jari, (float, int)): return error.ErrorTipeData(["float", "int"]) + return 2 * jari def persamaan_kuadrat( @@ -213,19 +212,15 @@ def faktorial(nilai: int) -> Union[int, float, error.Error, error.ErrorTipeData] """ # mengecek apakah variable tersebut bertipe data int atau float # jika tidak maka error - if isinstance(nilai, int): - if nilai == 0 or nilai == 1: - return 1 - elif nilai < 0: - return error.Error("Tidak bisa menggunakan angka negatif") - else: - hasil_rekursif = faktorial(nilai - 1) - if isinstance(hasil_rekursif, int): - return nilai * hasil_rekursif - else: - return hasil_rekursif - else: + if not isinstance(nilai, int): return error.ErrorTipeData(["int"]) + if nilai < 0: + return error.Error("Tidak bisa menggunakan angka negatif") + try: + return math.factorial(nilai) + except OverflowError: + # faktorial untuk nilai yang cukup besar sehingga menghasilkan overflow + return error.Error("Nilai terlalu besar untuk dihitung faktorialnya") def permutasi(nilai: int, r: int) -> Union[int, float, error.ErrorTipeData]: @@ -470,3 +465,102 @@ def sigmoid(vektor: np.ndarray) -> Union[error.ErrorTipeData, np.ndarray]: if not isinstance(vektor, np.ndarray): return error.ErrorTipeData(["numpy.narray"]) return 1 / (1 + np.exp(-vektor)) + + +def distribusi_binomial( + keberhasilan: int, + percobaan: int, + probabilitas: Union[float, int], +) -> Union[float, error.ErrorTipeData, error.ErrorValue]: + """ + mengembalikan probabilitas k keberhasilan dari n percobaan, dengan probabilitas p + untuk satu keberhasilan + + fungsi ini menggunakan fungsi faktorial untuk menghitung koefisien binomial + + Parameter: + keberhasilan (int): probabilitas + percobaan (int): percobaan dari distribusi binomial + probabilitas (int): probabilitas dari suatu keberhasilan + + Return: + (float): hasil dari distribusi binomial + """ + if keberhasilan > percobaan: + return error.ErrorValue( + "jumlah keberhasilan harus kurang dari atau sama dengan jumlah percobaan" + ) + if percobaan < 0 or keberhasilan < 0: + return error.ErrorValue("nilai percobaan dan keberhasilan tidak boleh negatif") + if not all(isinstance(data, (int)) for data in [keberhasilan, percobaan]): + return error.ErrorTipeData(["int"]) + if not 0 < probabilitas < 1: + return error.ErrorValue("nilai probabilitas harus 0 atau 1") + + probabilitas_kejadian = (probabilitas**keberhasilan) * ( + (1 - probabilitas) ** (percobaan - keberhasilan) + ) + + koefisien = float(math.factorial(percobaan)) + koefisien /= math.factorial(keberhasilan) * math.factorial(percobaan - keberhasilan) + return probabilitas_kejadian * koefisien + + +def gaussian( + x: int, mu: Union[float, int] = 0.0, sigma: Union[float, int] = 1.0 +) -> Union[float, error.ErrorTipeData]: + """ + fungsi gaussian, yang biasa disebut fungsi kurva lonceng adalah fungsi + untuk mendeskripsikan probabilitas distribusi data yang normal + """ + if not all( + isinstance(data, (float, int)) for data in [sigma, mu] + ) and not isinstance(x, int): + return error.ErrorTipeData(["float", "int"]) + return ( + 1 + / np.sqrt(2 * constant.PI * sigma**2) + * np.exp(-((x - mu) ** 2) / (2 * sigma**2)) + ) + + +def integral( + f: Callable[[float], float], a: int, b: int, iterasi: int = 4 +) -> Union[float, error.ErrorTipeData]: + """ + integral merupakan suatu konsep yang merupakan operasi kebalikan dari diferensiasi. + Integral memiliki dua bentuk utama: integral tak tentu (indefinite integral) + dan integral tentu (definite integral). + Args: + f (Callable[[float],float]): fungsi input + a (float): nilai awal + b (float): nilai atas + iterable (int, optional): mengatur putaran. Defaults to 4. + + """ + if not all(isinstance(data, (int)) for data in [a, b]): + return error.ErrorTipeData(["int"]) + if not isinstance(iterasi, int): + return error.ErrorTipeData(["int"]) + delta = (b - a) / iterasi + result = 0.5 * (f(a) + f(b)) + for i in range(1, iterasi): + result += f(a + i * delta) + return round(result * delta) + + +def turunan(f: Callable[[float], float], x: Union[int, float]) -> float: + """ + Args: + f (Callable[[float]float]: input fungsi + x (int) : input value + Return: + float : hasil dari kalkulasi apromasif + """ + # insial nilai h + h: float = 0.0001 + # mengecek tipe data pada nilai input pada paramter a dan b dan iterasi + if not isinstance(x, (float, int)): + return error.ErrorTipeData(["float", "int"]) + else: + return (f(x + h) - f(x)) / h diff --git a/OpenSeries/util/constant.py b/OpenSeries/util/constant.py index f3e3b70..85bbcd4 100644 --- a/OpenSeries/util/constant.py +++ b/OpenSeries/util/constant.py @@ -1,13 +1,24 @@ +from colorama import Fore, Style + # bilangan pi adalah nilai konstant dalam matematika yang merupakan perbandingan keliling # lingkaran dengan diameternya -pi: float = 3.14159265358979323846 +PI: float = 3.14159265358979323846 # bilangan euler adalah nilai konstant yang dimana nilai kira-kiranya sama dengan 2.71828 # dan dikarakterisasi dalam berbagai cara -bilangan_euler: float = 2.718281828459045235360 +BILANGAN_EULER: float = 2.718281828459045235360 + +# konstanta plank, yang dilambangankan dengan h, yang merupakan konstanta fisika +# fundamental yang menghubungkan energi foton dengan frekuensinya, nilainya disini +# adalah 6.6261 × 10⁻³⁴ (joule per detik) +KONSTANTA_PLANCK = 6.6261 * pow(10, -34) + +# variable ini juga mewakili dari konstanta planck, tetapi dinyatan dalam satuan +# elektron volt per detik (eV/s) nilainya adalah 4.1357 × 10⁻¹⁵ eV s⁻¹ +KONSTANTA_PLANCK = 4.1357 * pow(10, -15) # default error dari warna menggunakan kode ANSI escape # merah -red: str = "\033[91m" +red: str = Fore.RED # reset kembali warna ke default -reset_warna: str = "\033[0m" +reset_warna: str = Style.RESET_ALL diff --git a/OpenSeries/util/error.py b/OpenSeries/util/error.py index bb1106b..fd830fa 100644 --- a/OpenSeries/util/error.py +++ b/OpenSeries/util/error.py @@ -1,27 +1,47 @@ +# kostum error +# file error.py berisi tentang kustomisasi error dengan beberapa tujuan antara lain: +# - mendeteksi error terkait tipe data +# - membuat error kustom dengan pesan tertentu +# - menangani error terkait indeks saat melakukan indexing pada struktur data +# - menangani error terkait dengan validasi dari values +# - menampilkan error saat mencoba dengan pembagian dengan error from OpenSeries.util import constant as warna class ErrorTipeData(TypeError): """ - kelas untuk mendeteksi error dari tipe data + Kelas untuk mendeteksi error dari tipe data - parameter: + Parameter: expected_types (list[str]): tipe data yang dimasukkan - return: + Return: (str): pesan error tipe data sesuai dari inputan """ def __init__(self, expected_types: list[str]): - message = f"{warna.red}Error Tipe:{warna.reset_warna} tipe data Harus {' atau '.join(expected_types)}" + # mengecek apakah list expected_types tidak kosong + if not expected_types: + raise ValueError("tipe data dalam list tidak boleh kosong") + # mengecek apakah semua element di dalam expected_types adalah string + if not all(isinstance(data, str) for data in expected_types): + raise TypeError("element dari tipe data harus str (string)!") + + # membuat pesan error dengan memanggil method format_tipe_data + message = self.format_tipe_data(expected_types) super().__init__(message) + def format_tipe_data(self, tipe_data: list[str]) -> str: + # gabungkan element list menjadi string terpisah oleh `" atau "` + tipe_str = " atau ".join(map(str, tipe_data)) + return f"{warna.red}Error Tipe Data:{warna.reset_warna} tipe data harus {tipe_str}!" + class Error(Exception): """ - kelas untuk membuat kostumisasi error + Kelas untuk membuat kostumisasi error - parameter: + Parameter: pesan (str): pesan kostum yang ingin dimasukkan """ @@ -52,7 +72,7 @@ def __init__(self, pesan: str): class ErrorDibagiNol(ZeroDivisionError): """ - kelas untuk menampilkan error yang tidak bisa dibagi dengan nol + Kelas untuk menampilkan error yang tidak bisa dibagi dengan nol """ def __init__(self): diff --git a/README.md b/README.md index 02354f7..bf8fc03 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,9 @@ ![codequality](https://img.shields.io/codacy/grade/06ba6d6d345f4c15bf8e5cc3eac19d4d?style=flat-square&logo=codacy) ![build badge](https://img.shields.io/github/actions/workflow/status/bellshade/OpenSeries/pythontesting.yml?style=flat-square&logo=github&label=Build%20(%20Linux%2C%20Windows%2C%20MacOS)) +![PyPI - Version](https://img.shields.io/pypi/v/OpenSeriesBellshade?style=flat-square) +![PyPI - Implementation](https://img.shields.io/pypi/implementation/OpenSeriesBellshade?style=flat-square) +![PyPI - Downloads](https://img.shields.io/pypi/dd/OpenSeriesBellshade?style=flat-square) Project Untuk Menghitung Segala Jenis Persamaan atau Rumus-Rumus yang terdapat pada bangku sekolah (SMA/SMK/Sederajat) dan jenjang yang lebih lanjut. Project ini bertujuan untuk memudahkan siswa dalam menghitung persamaan atau problem-problem yang terdapat pada pelajaran sekolah (cheat egine untuk hitung-menghitung). diff --git a/dev-requirements.txt b/dev-requirements.txt index e079f8a..be30b4c 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1 +1,2 @@ +colorama pytest diff --git a/example/bilangan/armstrong.py b/example/bilangan/armstrong.py new file mode 100644 index 0000000..858f6df --- /dev/null +++ b/example/bilangan/armstrong.py @@ -0,0 +1,6 @@ +import OpenSeries.bilangan_istimewa as bilangan + +angka = 222 +angka_2 = 370 +print(f"{angka} adalah {bilangan.angka_armstrong(angka)}") +print(f"{angka_2} adalah {bilangan.angka_armstrong(angka_2)}") diff --git a/example/bilangan/automorphic.py b/example/bilangan/automorphic.py new file mode 100644 index 0000000..aed8498 --- /dev/null +++ b/example/bilangan/automorphic.py @@ -0,0 +1,4 @@ +import OpenSeries.bilangan_istimewa as bilangan + +contoh_angka = 25 +print(f"{contoh_angka} adalah {bilangan.angka_automorphic(contoh_angka)}") diff --git a/example/bilangan/pronic.py b/example/bilangan/pronic.py new file mode 100644 index 0000000..2a69a9a --- /dev/null +++ b/example/bilangan/pronic.py @@ -0,0 +1,4 @@ +import OpenSeries.bilangan_istimewa as bilangan + +contoh_angka = 30 +print(f"{contoh_angka} adalah {bilangan.angka_pronic(contoh_angka)}") diff --git a/example/bilangan/segitiga.py b/example/bilangan/segitiga.py new file mode 100644 index 0000000..fda11f7 --- /dev/null +++ b/example/bilangan/segitiga.py @@ -0,0 +1,4 @@ +import OpenSeries.bilangan_istimewa as bilangan + +angka = 3 +print(f"angka segitiga dari {angka} adalah {bilangan.angka_segitiga(angka)}") diff --git a/example/matematika/distribusi_binomial.py b/example/matematika/distribusi_binomial.py new file mode 100644 index 0000000..e9afc29 --- /dev/null +++ b/example/matematika/distribusi_binomial.py @@ -0,0 +1,6 @@ +import OpenSeries.matematika as matematika + +print( + "distribusi binomial dengan keberhasilan 3, percobaan 5, dan probabilitas 0.7 (70%)" +) +print(f"hasilnya adalah {matematika.distribusi_binomial(3, 5, 0.7)}") diff --git a/example/matematika/fungsi_gaussian.py b/example/matematika/fungsi_gaussian.py new file mode 100644 index 0000000..c85ab8a --- /dev/null +++ b/example/matematika/fungsi_gaussian.py @@ -0,0 +1,7 @@ +import OpenSeries.matematika as matematika +import numpy as np + +print(matematika.gaussian(15)) + +nilai_x = np.arange(15) +print(matematika.gaussian(nilai_x)) diff --git a/example/matematika/nilai_faktorial.py b/example/matematika/nilai_faktorial.py index 0ac7388..0775ccb 100644 --- a/example/matematika/nilai_faktorial.py +++ b/example/matematika/nilai_faktorial.py @@ -1,5 +1,5 @@ import OpenSeries.matematika as matematika -nilai_faktorial = 25 +nilai_faktorial = 20 print(f"menghitung nilai faktorial dari angka {nilai_faktorial}") print(f"hasilnya adalah : {matematika.faktorial(nilai_faktorial)}\n") diff --git a/pyproject.toml b/pyproject.toml index 0e893c8..27a2e26 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,12 +1,12 @@ [project] name = "OpenSeriesBellshade" -version = "1.6.6" +version = "1.7.0" dynamic = [ "dependencies" ] description = "library untuk membantu temen-temen dalam perhitungan matematika" readme = "README.md" -requires-python = ">=3.11.6" +requires-python = ">=3.10.0" keywords = [ "OpenSeriesBellshade", "openseries", @@ -21,8 +21,6 @@ classifiers = [ "License :: OSI Approved :: MIT License", "Natural Language :: English", "Natural Language :: Indonesian", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", diff --git a/requirements.txt b/requirements.txt index 24ce15a..e912b02 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ +colorama numpy diff --git a/setup.py b/setup.py index 23d76fc..0ae3bae 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ # nama dari project name="OpenSeries", # versi dari project - version="1.6.6", + version="1.7.0", # deskripsi singkat dari project description="library untuk membantu temen-temen SMA/SMK/Sederajat", # deskripsi detail tentang project diff --git a/testing/bilangan_istimewa_test.py b/testing/bilangan_istimewa_test.py new file mode 100644 index 0000000..55552b1 --- /dev/null +++ b/testing/bilangan_istimewa_test.py @@ -0,0 +1,67 @@ +import unittest +import OpenSeries.bilangan_istimewa as bilangan +import OpenSeries.util.error as error + + +class TestAngkaArmstrong(unittest.TestCase): + def test_angka_armstrong(self): + self.assertEqual(bilangan.angka_armstrong(153), "angka armstrong".capitalize()) + self.assertEqual(bilangan.angka_armstrong(370), "angka armstrong".capitalize()) + + def test_salah_armstrong(self): + self.assertEqual( + bilangan.angka_armstrong(222), "bukan angka armstrong".capitalize() + ) + self.assertEqual( + bilangan.angka_armstrong(444), "bukan angka armstrong".capitalize() + ) + + def test_salah_tipe_data_armstrong(self): + hasil = bilangan.angka_armstrong(333.2) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + +class TestAngkaAutomorphic(unittest.TestCase): + def test_tipe_data_angka(self): + with self.assertRaises(error.ErrorTipeData): + raise bilangan.angka_automorphic(12.3) + raise bilangan.angka_automorphic("23") + + def test_angka_negatif(self): + hasil = bilangan.angka_automorphic(-2) + self.assertEqual(hasil, "bukan angka automorphic".capitalize()) + + def test_valid_input(self): + hasil = bilangan.angka_automorphic(25) + self.assertEqual(hasil, "angka automorphic".capitalize()) + + +class TestAngkaPronic(unittest.TestCase): + def test_angka_pronic_return_tipe_data(self): + hasil = bilangan.angka_pronic(30) + self.assertIsInstance(hasil, str) + + hasil = bilangan.angka_pronic("30") + with self.assertRaises(error.ErrorTipeData): + raise hasil + + def test_angka_pronic_negatif(self): + hasil = bilangan.angka_pronic(-30) + self.assertIsInstance(hasil, str) + + +class TestAngkaSegitiga(unittest.TestCase): + def test_angka_segitiga(self): + self.assertEqual(bilangan.angka_segitiga(0), 0) + self.assertEqual(bilangan.angka_segitiga(3), 6) + + def test_angka_negatif(self): + hasil = bilangan.angka_segitiga(-1) + with self.assertRaises(error.Error): + raise hasil + + def test_beda_tipe_data(self): + hasil = bilangan.angka_segitiga("12") + with self.assertRaises(error.ErrorTipeData): + raise hasil diff --git a/testing/main_test.py b/testing/main_test.py index 8e0a59e..3864069 100644 --- a/testing/main_test.py +++ b/testing/main_test.py @@ -1,4 +1,5 @@ import unittest + from testing.matematika_test import ( TestKonversi, TestKelilingLingkaran, @@ -13,6 +14,10 @@ TestMatriksTranspose, TestFungsiEuler, TestSigmoid, + TestDistribusiBinomial, + TestGaussian, + TestIntegral, + TestDerivative, ) from testing.fisika_test import ( @@ -25,6 +30,13 @@ TestEfekDoppler, ) +from testing.bilangan_istimewa_test import ( + TestAngkaArmstrong, + TestAngkaAutomorphic, + TestAngkaPronic, + TestAngkaSegitiga, +) + from testing.statistika_test import TestFungsiEntropy, TestFungiStandardDeviasi if __name__ == "__main__": @@ -42,6 +54,10 @@ TestMatriksTranspose, TestFungsiEuler, TestSigmoid, + TestDistribusiBinomial, + TestGaussian, + TestIntegral, + TestDerivative, ] testing_fisika: list = [ @@ -59,6 +75,13 @@ TestFungiStandardDeviasi, ] + testing_angka_istimewa: list = [ + TestAngkaArmstrong, + TestAngkaAutomorphic, + TestAngkaPronic, + TestAngkaSegitiga, + ] + all_tests = unittest.TestSuite() for testing_math in testing_matematika: @@ -72,4 +95,9 @@ unittest.TestLoader().loadTestsFromTestCase(testing_statistik) ) + for testing_special_number in testing_angka_istimewa: + all_tests.addTest( + unittest.TestLoader().loadTestsFromTestCase(testing_special_number) + ) + unittest.TextTestRunner(verbosity=2).run(all_tests) diff --git a/testing/matematika_test.py b/testing/matematika_test.py index 718a374..6b2709f 100644 --- a/testing/matematika_test.py +++ b/testing/matematika_test.py @@ -98,17 +98,13 @@ def test_faktorial_nilai_nol(self): hasil = matematika.faktorial(0) self.assertEqual(hasil, 1) - def test_faktorial_nilai_int(self): - hasil = matematika.faktorial(5) - self.assertEqual(hasil, 120) - - def test_faktorial_nilai_float(self): - hasil = matematika.faktorial(2.5) + def test_faktorial_tipe_data_salah(self): + hasil = matematika.faktorial(20.0) with self.assertRaises(error.ErrorTipeData): raise hasil def test_faktorial_nilai_negatif(self): - hasil = matematika.faktorial(-20) + hasil = matematika.faktorial(-120) with self.assertRaises(error.Error): raise hasil @@ -225,3 +221,89 @@ def test_invalid_input(self): self.assertIsInstance(hasil, error.ErrorTipeData) with self.assertRaises(error.ErrorTipeData): raise hasil + + +class TestDistribusiBinomial(unittest.TestCase): + def test_valid_input(self): + hasil = matematika.distribusi_binomial(2, 5, 0.7) + self.assertAlmostEqual(hasil, 0.13230000000000006) + + def test_invalid_input_keberhasilan_lebih_besar_percobaan(self): + hasil = matematika.distribusi_binomial(5, 3, 0.5) + with self.assertRaises(error.ErrorValue): + raise hasil + + def test_invalid_input_negatif(self): + hasil = matematika.distribusi_binomial(-2, 4, 0.1) + with self.assertRaises(error.ErrorValue): + raise hasil + + def test_input_angka_tidak_integer(self): + hasil = matematika.distribusi_binomial(2.4, 4.2, 0.5) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + +class TestGaussian(unittest.TestCase): + def test_data_valid_input(self): + x = 5 + mu = 3 + sigma = 2 + ekspetasi_nilai = 0.12098536225957168 + hasil = matematika.gaussian(x, mu, sigma) + self.assertAlmostEqual(hasil, ekspetasi_nilai, places=10) + + +class TestIntegral(unittest.TestCase): + def test_nilai_integral(self): + def f(x): + return x * x + + a = 0 + b = 3 + hasil = matematika.integral(f, a, b) + + self.assertAlmostEqual(hasil, 9.00, places=2) + + def testing_tipe_input_data_string(self): + def f(x): + return x * x + + a = "0" + b = "3" + hasil = matematika.integral(f, a, b) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + def testing_tipe_iterasi_string(self): + def f(x): + return x * x + + a = 0 + b = 3 + iterasi = "4" + hasil = matematika.integral(a, b, iterasi) + with self.assertRaises(error.ErrorTipeData): + raise hasil + + +class TestDerivative(unittest.TestCase): + def setUp(self): + def f(x): + return x * x + + self.inputFungsi = f + self.inputValue = 4 + + def testing_input_value_integer(self): + hasil = matematika.turunan(self.inputFungsi, self.inputValue) + self.assertAlmostEqual(hasil, 8.000, places=3) + + def testing_input_value_desimal(self): + hasil = matematika.turunan(self.inputFungsi, float(self.inputValue)) + self.assertAlmostEqual(hasil, 8.000, places=3) + + def testing_input_value_string(self): + hasil = matematika.turunan(self.inputFungsi, str(self.inputValue)) + with self.assertRaises(error.ErrorTipeData): + raise hasil