-
Notifications
You must be signed in to change notification settings - Fork 0
/
float.py
107 lines (80 loc) · 2.87 KB
/
float.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import struct
"""
This is a helper class to convert normal IEEE754 floating point
number to/from 3-byte floating point value used in UT-88 calculator
firmware.
"""
class Float:
def __init__(self, value:float = 0):
self.from_float(value)
def is_negative(self):
return self._negative
def get_exponent(self):
return self._exponent
def get_mantissa(self):
return self._mantissa
def __str__(self) -> str:
return f"{'-' if self._negative else ''}{self._mantissa:06x}e{self._exponent}"
def __repr__(self) -> str:
return self.__str__()
def from_float(self, value: float):
float_bytes = struct.pack('f', value)
int_value = struct.unpack('I', float_bytes)[0]
print(f"Value = {value} {int_value:08x}")
if value == 0.:
self._negative = False
self._exponent = 0
self._mantissa = 0
else:
self._negative = (int_value & 0x80000000 != 0)
self._exponent = ((int_value & 0x7f800000) >> 23) - 127
self._mantissa = (int_value & 0x7fffff) | 0x800000
def from_sem(self, sign, exponent, mantissa):
self._negative = sign
self._exponent = exponent
self._mantissa = mantissa
self.normalize()
def normalize(self):
if self._mantissa == 0:
return
while self._mantissa < 0x800000:
self._mantissa <<= 1
self._exponent -= 1
while self._mantissa >= 0x01000000:
self._mantissa >>= 1
self._exponent += 1
def to_float(self):
if self._mantissa == 0 and self._exponent == 0:
return 0.
int_value = self._mantissa & 0x7fffff
int_value |= ((self._exponent + 127) & 0xff) << 23
int_value |= 0x80000000 if self._negative else 0
float_bytes = struct.pack('I', int_value)
return struct.unpack('f', float_bytes)[0]
def to_3_byte(self):
self.normalize()
if self._mantissa == 0:
return 0
exponent = self._exponent + 1
if exponent < 0:
exponent = (~exponent + 1) & 0xff
exponent |= 0x80
else:
exponent &= 0xff
mantissa = self._mantissa >> 10
mantissa |= 0x8000 if self._negative else 0
res = (exponent << 16) | (mantissa & 0xffff)
print(f"to_3_byte: {res:06x}")
return res
def from_3_byte(self, value):
if value == 0:
return self.from_float(0.)
self._exponent = (value >> 16) & 0xff
if self._exponent >= 0x80:
self._exponent = (~(self._exponent & 0x7f) + 1) & 0xff
self._negative = (value & 0x8000 != 0)
self._mantissa = (value & 0x3fff) << 10
if self._mantissa == 0:
self._exponent = 0
else:
self._exponent -= 1