From 9998db8aea9e6cb6b99f6802d2e80d3f538f265a Mon Sep 17 00:00:00 2001 From: icelal-kskn Date: Fri, 8 Nov 2024 13:53:14 +0300 Subject: [PATCH 1/2] Create halfprecision_ikram_celal_keskin.py --- Week06/halfprecision_ikram_celal_keskin.py | 139 +++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 Week06/halfprecision_ikram_celal_keskin.py diff --git a/Week06/halfprecision_ikram_celal_keskin.py b/Week06/halfprecision_ikram_celal_keskin.py new file mode 100644 index 0000000..71e47a3 --- /dev/null +++ b/Week06/halfprecision_ikram_celal_keskin.py @@ -0,0 +1,139 @@ +import numpy as np +# import os + +class HalfPrecision: + """ + This class converting a floating point number to half precision format. + The half precision format is a 16-bit format with 1 sign bit, 5 exponent bits, and 10 mantissa bits. + The sign bit is 0 for positive numbers and 1 for negative numbers. + + Attributes: + number: float + + Raises: + TypeError: If the input is the string, bool, list, tuple, or set. + TypeError: If the input cannot be converted to a float. + + Returns: + str: The half precision format of the input number. + """ + def __init__(self,number): + if isinstance(number,(str,bool,list,tuple,set)): + raise TypeError(f"Invalid input {type(number)}") + try: + self.__number = float(number) + except Exception as e: + raise TypeError("Input {} cannot be converted to a float".format(e.args[0])) + + def __str__(self)->str: + """ + Returns the half precision format of the input number. + + Returns: + str: The half precision format of the input number. + """ + return self.__calculate_precision(5,10,self.__number) #for half precision + + def __calculate_precision(self,exponent_length:int,mantissa_length:int,number:float)->str: + """ + This function calculates the half precision format of the input number. + """ + sign= False + + if number < 0 or np.signbit(number): + sign = True + number = -number + + if np.isinf(number): + return f"{int(sign)}{'1'*exponent_length}{'0'*mantissa_length}" + + bias= 2**(exponent_length-1)-1 + mantissa,power = self.__calculate_mantissa(mantissa_length,number) + + if power == None: + return f"{int(sign)}{'0'*exponent_length}{'0'*mantissa_length}" + + exponent = self.__calculate_exponent(bias,power,exponent_length) + + return f"{int(sign)}{exponent}{mantissa}" + + def __calculate_exponent(self,bias:int,power:int,exponent_length)->str: + """ + This function calculates the exponent part of the half precision format. + """ + binary_exponent = self.__integer_to_binary(bias+power) + + if len(binary_exponent) < exponent_length: + binary_exponent = '0' * (exponent_length - len(binary_exponent)) + binary_exponent + + return binary_exponent + + def __calculate_mantissa(self,mantissa_length:int,number:float)->str: + """ + This function calculates the mantissa part of the half precision format. + """ + integer_part,decimal_part = f"{number:.20f}".split(".") + integer_part = self.__integer_to_binary(integer_part) + decimal_part = self.__decimal_to_binary(decimal_part) + + mantissa = f'{integer_part}.{decimal_part}' + + if not '1' in mantissa: + return '0'*mantissa_length,None + + power = 0 + index1 = mantissa_length + + indexdot = mantissa.index(".") + index1 = mantissa.index("1") + mantissa = mantissa[index1+1:].replace(".","") + power = indexdot - index1 if indexdot < index1 else indexdot - index1 -1 + + if len(mantissa)< mantissa_length: + mantissa += '0' * (mantissa_length - len(mantissa)) + elif len(mantissa)> mantissa_length: + mantissa = mantissa[:mantissa_length-1] + '1' + + + return mantissa,power + + def __integer_to_binary(self,number:int)->str: + + result = "" + number = int(number) + + if number == 0: + return "0" + + while number != 0: + remainder = number % 2 + result += str(remainder) + number //= 2 + + return result[::-1] + + def __decimal_to_binary(self,number:float)->str: + number=float(f"0.{number.split("0")[0]}") + + if number == 0: + return '' + + binary = '' + while number > 0 and len(binary) < 100: + + number *= 2 + if number >= 1: + binary += '1' + number -= 1 + else: + binary += '0' + + return binary + + + +# if __name__=="__main__": +# os.system("pytest -v test_halfprecision.py") + + + From 82775a51e6216fc747b7c66d52ad46c1994d9de6 Mon Sep 17 00:00:00 2001 From: icelal-kskn Date: Wed, 13 Nov 2024 09:21:23 +0300 Subject: [PATCH 2/2] Update halfprecision_ikram_celal_keskin.py - Implemented the new method what is checks the input number is calculatable in custom precision - Changed float(number) to number / 1 - Now matissa is truncating exact position --- Week06/halfprecision_ikram_celal_keskin.py | 24 ++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/Week06/halfprecision_ikram_celal_keskin.py b/Week06/halfprecision_ikram_celal_keskin.py index 71e47a3..ab6724a 100644 --- a/Week06/halfprecision_ikram_celal_keskin.py +++ b/Week06/halfprecision_ikram_celal_keskin.py @@ -1,5 +1,4 @@ import numpy as np -# import os class HalfPrecision: """ @@ -21,7 +20,7 @@ def __init__(self,number): if isinstance(number,(str,bool,list,tuple,set)): raise TypeError(f"Invalid input {type(number)}") try: - self.__number = float(number) + self.__number = number / 1 except Exception as e: raise TypeError("Input {} cannot be converted to a float".format(e.args[0])) @@ -44,6 +43,8 @@ def __calculate_precision(self,exponent_length:int,mantissa_length:int,number:fl sign = True number = -number + number = self.__is_calculatable_mantissa(number,mantissa_length,exponent_length) + if np.isinf(number): return f"{int(sign)}{'1'*exponent_length}{'0'*mantissa_length}" @@ -92,11 +93,22 @@ def __calculate_mantissa(self,mantissa_length:int,number:float)->str: if len(mantissa)< mantissa_length: mantissa += '0' * (mantissa_length - len(mantissa)) elif len(mantissa)> mantissa_length: - mantissa = mantissa[:mantissa_length-1] + '1' - + mantissa = mantissa[:mantissa_length] #Truncating + # mantissa = mantissa[:mantissa_length-1] + '1' #Rounding return mantissa,power + + def __is_calculatable_mantissa(self, number: float, mantissa_length: int, exponent_length: int) -> float: + """ + This function checks if the input number is calculatable in custom precision format. + """ + max_number = 2**(2**(exponent_length-1)-1) * (2-2**(-mantissa_length)) + if number > max_number: + return np.inf + + return number + def __integer_to_binary(self,number:int)->str: result = "" @@ -132,8 +144,4 @@ def __decimal_to_binary(self,number:float)->str: -# if __name__=="__main__": -# os.system("pytest -v test_halfprecision.py") - -