def is_zero(self) -> bool: """ 모든 비트가 0인지 확인하는 함수 :return: 모든 비트가 0인지 여부 """ return not self.sign and BitOperation.is_empty(self.exponents) and BitOperation.is_empty(self.fractions)
def str_to_minor(real: List[Bit], val: str, digit: int, length: int) -> (List[Bit], int): """ 소수점 아래의 값을 표현하는 문자열을 읽어 Bit List를 생성하는 함수 :param real: 소수점 위의 값의 Bit List :param val: 소수점 아래의 값을 표현하는 문자열 :param digit: 소수점 위의 자리수 :param length: 원하는 Bit List의 길이 :return: 문자열 실수값에 해당하는 Bit List, 자리수 """ real, ten = BitOperation.equalize_bit_length( real, BitOperation.num_map['10'], length) base = BitOperation.fit_bits(BitOperation.num_map['1'], length) twenty = BitOperation.raw_lshift_bits(ten, 1) remain = BitOperation.empty_bits(length) shift = 1 index = 0 while True: if index < len(val) and index < 6: remain = Arithmetic.raw_mul_bits(remain, twenty) next_digit = BitOperation.lshift_bits( BitOperation.num_map[val[index]], shift, length) remain, _ = Arithmetic.raw_add_bits(remain, next_digit) index += 1 shift += 1 base = Arithmetic.raw_mul_bits(base, ten) else: remain = BitOperation.raw_lshift_bits(remain, 1) if BitOperation.is_empty(BitOperation.raw_or_bits( remain, real)): return real, -127 real = BitOperation.raw_lshift_bits(real, 1) if BitOperation.raw_ge_bits(remain, base): real, _ = Arithmetic.add_bits(real, BitOperation.num_map['1'], length) remain, _ = Arithmetic.sub_bits(remain, base, length) if BitOperation.first_bit_index(real) == 0: remain = BitOperation.raw_lshift_bits(remain, 1) if BitOperation.raw_ge_bits(remain, base): real = BitOperation.or_bits(real, BitOperation.num_map['1'], length) break elif BitOperation.is_empty(real): digit -= 1 return real, digit
def raw_div_bits(a: List[Bit], b: List[Bit]) -> List[Bit]: """ 같은 길이의 Bit List를 나누는 ( / ) 함수 left-shift ( << ) 연산과 add ( + ) 연산, lower-equal ( <= ) 연산을 통해 나눗셈 구현 상위 비트부터 하위 비트까지 값을 빼면서 몫을 구함 :param a: / 앞의 Bit List :param b: 나눌 Bit List :return: a / b의 값인 Bit List """ if BitOperation.is_empty(b): raise ZeroDivisionError() remain = BitOperation.empty_bits(len(a)) res = BitOperation.empty_bits(len(a)) one = BitOperation.fit_bits(BitOperation.num_map['1'], len(a)) for i in range(len(a) - 1, -1, -1): first_bit = BitOperation.first_bit_index(b) if first_bit < i: continue div = BitOperation.raw_lshift_bits(b, i) sum_val, overflow = Arithmetic.raw_add_bits(remain, div) if overflow: continue if BitOperation.raw_le_bits(sum_val, a): remain, _ = Arithmetic.raw_add_bits(remain, div) quotient = BitOperation.raw_lshift_bits(one, i) res = BitOperation.raw_or_bits(res, quotient) return res
def __mul__(self, other: "Float") -> "Float": """ Binary Mul 연산 ( * )을 위한 operator overloading :param other: Float 타입 가정 :return: 새로운 Float 객체로 return """ a_frac = BitOperation.fraction_bits(self.fractions) b_frac = BitOperation.fraction_bits(other.fractions) exp, _ = Arithmetic.add_bits(self.exponents, other.exponents, self.exponent_len) bias = Arithmetic.str_to_integer('127', self.exponent_len) exp, _ = Arithmetic.raw_sub_bits(exp, bias) extra = BitOperation.empty_bits(self.fraction_len + 1) mul = a_frac over = BitOperation.empty_bits(self.fraction_len + 1) for bit in b_frac[:0:-1]: if bit: extra, overflow = Arithmetic.raw_add_bits(extra, mul) if overflow: over, _ = Arithmetic.add_bits(over, BitOperation.num_map['1'], self.fraction_len+1) mul = BitOperation.raw_lshift_bits(mul, 1) if BitOperation.is_empty(mul): break res = BitOperation.empty_bits(self.fraction_len + 1) mul = a_frac for bit in b_frac: if bit: res, overflow = Arithmetic.raw_add_bits(res, mul) if overflow: res = BitOperation.raw_rshift_bits(res, 1) res[0] = overflow exp, _ = Arithmetic.add_bits(exp, BitOperation.num_map['1'], self.exponent_len) mul = BitOperation.raw_rshift_bits(mul, 1) mul = BitOperation.raw_rshift_bits(mul, 1) if BitOperation.is_empty(mul): break res, _ = Arithmetic.raw_add_bits(res, over) res = res[1:] return Float(exp, res, self.sign ^ other.sign)
def raw_add_bits(a: List[Bit], b: List[Bit]) -> (List[Bit], Bit): """ 같은 길이의 Bit List를 더하는 ( + ) 함수 덧셈 결과 overflow 되었는지 여부를 함께 return and ( & ) 연산, xor ( ^ ) 연산과 left-shift ( << ) 연산을 통해 덧셈을 구현 :param a: 더할 Bit List :param b: 더할 Bit List :return: a + b의 값인 Bit List, overflow 된 Bit """ if BitOperation.is_empty(b): return a, Bit() carry_0 = BitOperation.raw_and_bits(a, b) remain = BitOperation.raw_xor_bits(a, b) carry = BitOperation.raw_lshift_bits(carry_0, 1) res, overflow = Arithmetic.raw_add_bits(remain, carry) return res, overflow ^ carry_0[0]
def shift_fraction(a_exp: List[Bit], b_exp: List[Bit], b_frac: List[Bit]): """ float의 exponent 값 차이만큼 shift 한 fraction 값 연산 right-shift 연산 할 때 생략된 값이 있을 때 1을 더함 :param a_exp: 비교하는 exponent :param b_exp: 비교하는 exponent :param b_frac: shift 연산할 fraction :return: shift 연산 된 fraction """ diff, _ = Arithmetic.raw_sub_bits(a_exp, b_exp) diff = BitOperation.binary_to_decimal(diff) b_fraction = BitOperation.raw_rshift_bits(b_frac, diff) if not BitOperation.is_empty(b_frac[:diff]): b_fraction, _ = Arithmetic.add_bits(b_fraction, BitOperation.num_map['1'], len(b_fraction)) return b_fraction return b_fraction
def is_inf(self) -> bool: """ 값이 inf 인지 확인하는 함수 :return: exponent가 모두 1이고 fraction은 모두 0인지 여부 """ return BitOperation.is_empty(BitOperation.invert_bits(self.exponents)) and BitOperation.is_empty(self.fractions)
def is_nan(self) -> bool: """ 값이 nan 인지 확인하는 함수 :return: exponent가 모두 1이고 fraction은 모두 0이 아닌지 여부 """ return BitOperation.is_empty(BitOperation.invert_bits(self.exponents)) and not BitOperation.is_empty(self.fractions)
def is_zero(self) -> bool: """ 모든 비트가 0인지 확인하는 함수 :return: 모든 비트가 0인지 여부 """ return not self.sign and BitOperation.is_empty(self.bits)