The code below deals with expansion of single-precision IEEE 754 floating point values to double-precision (and vice-versa) without losing detail of NaN bit-patterns. ```python def to_bytes(self): """Converts this 32-bit single-precision floating point value to its binary32 format, taking care to preserve the quiet/signalling bit-pattern of NaN values, unlike its `struct.pack('>f', ...)` equivalent. ```python >>> Float.from_bytes(b'\\x7f\\x80\\x00{') Float(nan) >>> Float.from_bytes(b'\\x7f\\x80\\x00{').to_bytes() b'\\x7f\\x80\\x00{' >>> struct.unpack('>f', b'\\x7f\\x80\\x00{')[0] nan >>> Float(struct.unpack('>f', b'\\x7f\\x80\\x00{')[0]).to_bytes() b'\\x7f\\xc0\\x00{' >>> struct.pack('>f', struct.unpack('>f', b'\\x7f\\x80\\x00{')[0]) b'\\x7f\\xc0\\x00{' ``` (Note well the difference between `7f80007b` and `7fc0007b`!) """ if math.isnan(self.value) or math.isinf(self.value): dbs = struct.pack('>d', self.value) vd = struct.unpack('>Q', dbs)[0] sign = vd >> 63 payload = (vd >> 29) & 0x007fffff vf = (sign << 31) | 0x7f800000 | payload return struct.pack('>I', vf) else: return struct.pack('>f', self.value) @staticmethod def from_bytes(bs): """Converts a 4-byte-long byte string to a 32-bit single-precision floating point value wrapped in a [Float][preserves.values.Float] instance. Takes care to preserve the quiet/signalling bit-pattern of NaN values, unlike its `struct.unpack('>f', ...)` equivalent. ```python >>> Float.from_bytes(b'\\x7f\\x80\\x00{') Float(nan) >>> Float.from_bytes(b'\\x7f\\x80\\x00{').to_bytes() b'\\x7f\\x80\\x00{' >>> struct.unpack('>f', b'\\x7f\\x80\\x00{')[0] nan >>> Float(struct.unpack('>f', b'\\x7f\\x80\\x00{')[0]).to_bytes() b'\\x7f\\xc0\\x00{' >>> struct.pack('>f', struct.unpack('>f', b'\\x7f\\x80\\x00{')[0]) b'\\x7f\\xc0\\x00{' ``` (Note well the difference between `7f80007b` and `7fc0007b`!) """ vf = struct.unpack('>I', bs)[0] if (vf & 0x7f800000) == 0x7f800000: # NaN or inf. Preserve quiet/signalling bit by manually expanding to double-precision. sign = vf >> 31 payload = vf & 0x007fffff dbs = struct.pack('>Q', (sign << 63) | 0x7ff0000000000000 | (payload << 29)) return Float(struct.unpack('>d', dbs)[0]) else: return Float(struct.unpack('>f', bs)[0]) ```