From 5b663f6b7fdd380408cdcd706e3ee6da517fa5a0 Mon Sep 17 00:00:00 2001 From: avivfaraj <73610201+avivfaraj@users.noreply.github.com> Date: Fri, 3 Sep 2021 19:43:50 -0400 Subject: [PATCH 01/13] added gamma_function --- physics/gamma_function.py | 82 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 physics/gamma_function.py diff --git a/physics/gamma_function.py b/physics/gamma_function.py new file mode 100644 index 000000000000..bdfe6f0f3446 --- /dev/null +++ b/physics/gamma_function.py @@ -0,0 +1,82 @@ +""" +Gamma function is a very useful tool in physics. +It helps calculating complex integral in a convenient way. +""" + +# Importing packages +from math import sqrt, pi +from re import match +from typing import Union + + +def gamma(num : Union[int, float]) -> Union[int, float]: + """ + Calculates the value of Gamma function of num + where num is either an integer (1,2,3..) or a half-integer (0.5,1.5,2.5...). + Implemented using recursion + Examples: + >>> Gamma of: 0.5 + √π + >>> Gamma of: 2 + 1 + >>> Gamma of: 3.5 + 1.875√π + """ + if num == 1: + return 1 + elif num == 0.5: + return sqrt(pi) + elif num > 1: + return (num - 1) * gamma(num - 1) + else: + # Error + return -2 + + +def test_gamma() -> None: + """ + >>> test_gamma() + """ + assert sqrt(pi) == gamma(0.5) + assert 1 == gamma(1) + assert 1 == gamma(2) + + +if __name__ == "__main__": + # Initialize boolean + number = True + # Get input from user + input_ = input("Gamma of: ") + # Ensure valid input + try: + # Ensure input matches half-integer (float) pattern + if match(r'^[0-9]*\.5$', input_): + # Convert string to float + num = float(input_) + # Ensure input matches an integer pattern + elif match(r'^[1-9][0-9]*$', input_): + # Convert string to int + num = int(input_) + # Input is not a valid number + else: + # raise an error + raise ValueError + # Ensure print an error message + except ValueError: + print("Invalid input: Must be an integer or an half-integer!") + number = False + finally: + # Ensure input is a valid number + if number: + # Ensure input is an integer + if (isinstance(gamma(num), int)): + # Print result + print(gamma(num)) + # Otherwise print results with √π (gamma of 0.5 is √π) + # Therefore all results will be a number times √π + else: + results = "{result:.4f}".format(result=gamma(num) / sqrt(pi)) + results = results.rstrip('0').rstrip('.') + if results == "1": + results = "" + print(results + "\u221A\u03c0") From a267f40efb874750705e9b6c7c638c95c42530d8 Mon Sep 17 00:00:00 2001 From: avivfaraj <73610201+avivfaraj@users.noreply.github.com> Date: Fri, 3 Sep 2021 19:50:14 -0400 Subject: [PATCH 02/13] Add files via upload --- physics/gamma_function.py | 1 + 1 file changed, 1 insertion(+) diff --git a/physics/gamma_function.py b/physics/gamma_function.py index bdfe6f0f3446..395968aeb99b 100644 --- a/physics/gamma_function.py +++ b/physics/gamma_function.py @@ -1,6 +1,7 @@ """ Gamma function is a very useful tool in physics. It helps calculating complex integral in a convenient way. +for more info: https://en.wikipedia.org/wiki/Gamma_function """ # Importing packages From 051167d82af2cb4ebbca76c01e949de65ec850ec Mon Sep 17 00:00:00 2001 From: avivfaraj <73610201+avivfaraj@users.noreply.github.com> Date: Sat, 4 Sep 2021 10:29:27 -0400 Subject: [PATCH 03/13] Resolved issue with str.format And also changed output to math notation --- physics/gamma_function.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/physics/gamma_function.py b/physics/gamma_function.py index 395968aeb99b..dff5dff85a5b 100644 --- a/physics/gamma_function.py +++ b/physics/gamma_function.py @@ -64,11 +64,12 @@ def test_gamma() -> None: raise ValueError # Ensure print an error message except ValueError: - print("Invalid input: Must be an integer or an half-integer!") + print("Error: Input must be an integer or an half-integer!") number = False finally: # Ensure input is a valid number if number: + print(f"\u0393({num}) = ", end="") # Ensure input is an integer if (isinstance(gamma(num), int)): # Print result @@ -76,8 +77,9 @@ def test_gamma() -> None: # Otherwise print results with √π (gamma of 0.5 is √π) # Therefore all results will be a number times √π else: - results = "{result:.4f}".format(result=gamma(num) / sqrt(pi)) + results = f"{gamma(num) / sqrt(pi):.4f}" results = results.rstrip('0').rstrip('.') if results == "1": results = "" print(results + "\u221A\u03c0") + From 902e13a1b1b424c4d57aeea27ea071077fd61d3e Mon Sep 17 00:00:00 2001 From: avivfaraj <73610201+avivfaraj@users.noreply.github.com> Date: Sun, 5 Sep 2021 12:51:16 -0400 Subject: [PATCH 04/13] Update gamma_function.py --- physics/gamma_function.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/physics/gamma_function.py b/physics/gamma_function.py index dff5dff85a5b..87f9d6bbfbd4 100644 --- a/physics/gamma_function.py +++ b/physics/gamma_function.py @@ -29,9 +29,8 @@ def gamma(num : Union[int, float]) -> Union[int, float]: return sqrt(pi) elif num > 1: return (num - 1) * gamma(num - 1) - else: - # Error - return -2 + # Error + return -2 def test_gamma() -> None: From 6ccad7f71b3e1dd4fbcc1b818356969e20d550c6 Mon Sep 17 00:00:00 2001 From: Aviv Faraj <73610201+avivfaraj@users.noreply.github.com> Date: Mon, 6 Sep 2021 10:20:24 -0400 Subject: [PATCH 05/13] Rename physics/gamma_function.py to maths/gamma_recursive.py --- physics/gamma_function.py => maths/gamma_recursive.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename physics/gamma_function.py => maths/gamma_recursive.py (100%) diff --git a/physics/gamma_function.py b/maths/gamma_recursive.py similarity index 100% rename from physics/gamma_function.py rename to maths/gamma_recursive.py From a99383e50de3ee0c1fcfca9cecfaf18381081ed4 Mon Sep 17 00:00:00 2001 From: Aviv Faraj <73610201+avivfaraj@users.noreply.github.com> Date: Mon, 6 Sep 2021 12:57:22 -0400 Subject: [PATCH 06/13] Fixes: #4709 Fixed issues for pre-commit test --- maths/gamma_recursive.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/maths/gamma_recursive.py b/maths/gamma_recursive.py index 87f9d6bbfbd4..d8f6577df63f 100644 --- a/maths/gamma_recursive.py +++ b/maths/gamma_recursive.py @@ -50,11 +50,11 @@ def test_gamma() -> None: # Ensure valid input try: # Ensure input matches half-integer (float) pattern - if match(r'^[0-9]*\.5$', input_): + if match(r"^[0-9]*\.5$", input_): # Convert string to float num = float(input_) # Ensure input matches an integer pattern - elif match(r'^[1-9][0-9]*$', input_): + elif match(r"^[1-9][0-9]*$", input_): # Convert string to int num = int(input_) # Input is not a valid number @@ -70,14 +70,14 @@ def test_gamma() -> None: if number: print(f"\u0393({num}) = ", end="") # Ensure input is an integer - if (isinstance(gamma(num), int)): + if isinstance(gamma(num), int): # Print result print(gamma(num)) # Otherwise print results with √π (gamma of 0.5 is √π) # Therefore all results will be a number times √π else: results = f"{gamma(num) / sqrt(pi):.4f}" - results = results.rstrip('0').rstrip('.') + results = results.rstrip("0").rstrip(".") if results == "1": results = "" print(results + "\u221A\u03c0") From c2d76238acf18b93b72963dfdbd603e452c7f8b1 Mon Sep 17 00:00:00 2001 From: Aviv Faraj <73610201+avivfaraj@users.noreply.github.com> Date: Mon, 6 Sep 2021 14:08:39 -0400 Subject: [PATCH 07/13] Fixes: #4709 solved issues with doctests And comments --- maths/gamma_recursive.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/maths/gamma_recursive.py b/maths/gamma_recursive.py index d8f6577df63f..c1a3ae227ebf 100644 --- a/maths/gamma_recursive.py +++ b/maths/gamma_recursive.py @@ -16,12 +16,12 @@ def gamma(num : Union[int, float]) -> Union[int, float]: where num is either an integer (1,2,3..) or a half-integer (0.5,1.5,2.5...). Implemented using recursion Examples: - >>> Gamma of: 0.5 - √π - >>> Gamma of: 2 + >>> gamma(0.5) + 1.7724538509055159 + >>> gamma(2) 1 - >>> Gamma of: 3.5 - 1.875√π + >>> gamma(3.5) + 3.3233509704478426 """ if num == 1: return 1 @@ -43,9 +43,7 @@ def test_gamma() -> None: if __name__ == "__main__": - # Initialize boolean - number = True - # Get input from user + is_number = True input_ = input("Gamma of: ") # Ensure valid input try: @@ -64,10 +62,10 @@ def test_gamma() -> None: # Ensure print an error message except ValueError: print("Error: Input must be an integer or an half-integer!") - number = False + is_number = False finally: # Ensure input is a valid number - if number: + if is_number: print(f"\u0393({num}) = ", end="") # Ensure input is an integer if isinstance(gamma(num), int): From 5c1af2d4bbdf8c5f5afb0232adfc0cf91e7366de Mon Sep 17 00:00:00 2001 From: Aviv Faraj <73610201+avivfaraj@users.noreply.github.com> Date: Mon, 6 Sep 2021 14:33:43 -0400 Subject: [PATCH 08/13] Fixes: #4709 Added failed tests to doctest --- maths/gamma_recursive.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/maths/gamma_recursive.py b/maths/gamma_recursive.py index c1a3ae227ebf..3d88ccec184d 100644 --- a/maths/gamma_recursive.py +++ b/maths/gamma_recursive.py @@ -22,6 +22,10 @@ def gamma(num : Union[int, float]) -> Union[int, float]: 1 >>> gamma(3.5) 3.3233509704478426 + >>> gamma(-4) + -2 + >>> gamma(-1) + -2 """ if num == 1: return 1 From 4b5755d60c8a811557a1cb261f5c003043bc033e Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Mon, 6 Sep 2021 23:27:16 +0200 Subject: [PATCH 09/13] Align with Python's Standard Library math.gamma() Replicate the exceptions of https://docs.python.org/3/library/math.html#math.gamma --- maths/gamma_recursive.py | 61 +++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/maths/gamma_recursive.py b/maths/gamma_recursive.py index 3d88ccec184d..f9e6d1fe8256 100644 --- a/maths/gamma_recursive.py +++ b/maths/gamma_recursive.py @@ -1,49 +1,72 @@ """ -Gamma function is a very useful tool in physics. +Gamma function is a very useful tool in math and physics. It helps calculating complex integral in a convenient way. for more info: https://en.wikipedia.org/wiki/Gamma_function -""" -# Importing packages +Python's Standard Library math.gamma() function overflows around gamma(171.624). +""" from math import sqrt, pi from re import match -from typing import Union -def gamma(num : Union[int, float]) -> Union[int, float]: +def gamma(num: float) -> float: """ Calculates the value of Gamma function of num - where num is either an integer (1,2,3..) or a half-integer (0.5,1.5,2.5...). + where num is either an integer (1, 2, 3..) or a half-integer (0.5, 1.5, 2.5 ...). Implemented using recursion Examples: + >>> from math import isclose, gamma as math_gamma >>> gamma(0.5) 1.7724538509055159 >>> gamma(2) - 1 + 1.0 >>> gamma(3.5) 3.3233509704478426 + >>> gamma(171.5) + 9.483367566824795e+307 + >>> all(isclose(gamma(num), math_gamma(num)) for num in (0.5, 2, 3.5, 171.5)) + True + >>> gamma(0) + Traceback (most recent call last): + ... + ValueError: math domain error + >>> gamma(-1.1) + Traceback (most recent call last): + ... + ValueError: math domain error >>> gamma(-4) - -2 - >>> gamma(-1) - -2 + Traceback (most recent call last): + ... + ValueError: math domain error + >>> gamma(172) + Traceback (most recent call last): + ... + OverflowError: math range error + >>> gamma(1.1) + Traceback (most recent call last): + ... + NotImplementedError: num must be an integer or a half-integer """ - if num == 1: - return 1 + if num <= 0: + raise ValueError("math domain error") + if num > 171.5: + raise OverflowError("math range error") + elif num - int(num) not in (0, 0.5): + raise NotImplementedError("num must be an integer or a half-integer") elif num == 0.5: return sqrt(pi) - elif num > 1: - return (num - 1) * gamma(num - 1) - # Error - return -2 + else: + return 1.0 if num == 1 else (num - 1) * gamma(num - 1) def test_gamma() -> None: """ >>> test_gamma() """ - assert sqrt(pi) == gamma(0.5) - assert 1 == gamma(1) - assert 1 == gamma(2) + assert gamma(0.5) == sqrt(pi) + assert gamma(1) == 1.0 + assert gamma(1.5) == sqrt(pi) + assert gamma(2) == 1.0 if __name__ == "__main__": From 100c16ff07dd58fe9beb6cd9b7fa6b3b6dbedd50 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Mon, 6 Sep 2021 23:29:51 +0200 Subject: [PATCH 10/13] Update gamma_recursive.py --- maths/gamma_recursive.py | 1 - 1 file changed, 1 deletion(-) diff --git a/maths/gamma_recursive.py b/maths/gamma_recursive.py index f9e6d1fe8256..fb7292dbec00 100644 --- a/maths/gamma_recursive.py +++ b/maths/gamma_recursive.py @@ -106,4 +106,3 @@ def test_gamma() -> None: if results == "1": results = "" print(results + "\u221A\u03c0") - From ce11d458a9e9689c376cce6e3c2c3fb660d35167 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Mon, 6 Sep 2021 23:32:14 +0200 Subject: [PATCH 11/13] Update gamma_recursive.py --- maths/gamma_recursive.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maths/gamma_recursive.py b/maths/gamma_recursive.py index fb7292dbec00..f370a2c3db71 100644 --- a/maths/gamma_recursive.py +++ b/maths/gamma_recursive.py @@ -5,7 +5,7 @@ Python's Standard Library math.gamma() function overflows around gamma(171.624). """ -from math import sqrt, pi +from math import pi, sqrt from re import match From de5562e57bd916ebbaf86f5216661cf1146fcdc5 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Mon, 6 Sep 2021 23:49:13 +0200 Subject: [PATCH 12/13] Update gamma_recursive.py --- maths/gamma_recursive.py | 45 +++++++--------------------------------- 1 file changed, 8 insertions(+), 37 deletions(-) diff --git a/maths/gamma_recursive.py b/maths/gamma_recursive.py index f370a2c3db71..cc10ae2aa32d 100644 --- a/maths/gamma_recursive.py +++ b/maths/gamma_recursive.py @@ -65,44 +65,15 @@ def test_gamma() -> None: """ assert gamma(0.5) == sqrt(pi) assert gamma(1) == 1.0 - assert gamma(1.5) == sqrt(pi) assert gamma(2) == 1.0 if __name__ == "__main__": - is_number = True - input_ = input("Gamma of: ") - # Ensure valid input - try: - # Ensure input matches half-integer (float) pattern - if match(r"^[0-9]*\.5$", input_): - # Convert string to float - num = float(input_) - # Ensure input matches an integer pattern - elif match(r"^[1-9][0-9]*$", input_): - # Convert string to int - num = int(input_) - # Input is not a valid number - else: - # raise an error - raise ValueError - # Ensure print an error message - except ValueError: - print("Error: Input must be an integer or an half-integer!") - is_number = False - finally: - # Ensure input is a valid number - if is_number: - print(f"\u0393({num}) = ", end="") - # Ensure input is an integer - if isinstance(gamma(num), int): - # Print result - print(gamma(num)) - # Otherwise print results with √π (gamma of 0.5 is √π) - # Therefore all results will be a number times √π - else: - results = f"{gamma(num) / sqrt(pi):.4f}" - results = results.rstrip("0").rstrip(".") - if results == "1": - results = "" - print(results + "\u221A\u03c0") + from doctest import testmod + + testmod() + num = 1 + while num: + num = float(input("Gamma of: ")) + print(f"gamma({num}) = {gamma(num)}") + print("\nEnter 0 to exit...") From 6a1e1b9f5122817d8753503076c4f4a74b921a11 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Mon, 6 Sep 2021 23:51:54 +0200 Subject: [PATCH 13/13] Update gamma_recursive.py --- maths/gamma_recursive.py | 1 - 1 file changed, 1 deletion(-) diff --git a/maths/gamma_recursive.py b/maths/gamma_recursive.py index cc10ae2aa32d..683d7adb1aa8 100644 --- a/maths/gamma_recursive.py +++ b/maths/gamma_recursive.py @@ -6,7 +6,6 @@ Python's Standard Library math.gamma() function overflows around gamma(171.624). """ from math import pi, sqrt -from re import match def gamma(num: float) -> float: