I am trying to convert a floating number to 48‑bit Real
(from Borland Pascal) in Python. I have found this method written in C# (I think):
static byte[] DoubleToReal48(double d)
{
byte[] r = new byte[6];
long bits = BitConverter.DoubleToInt64Bits(d);
bool negative = ((bits >> 63) & 1) != 0;
long exponent = ((bits >> 52) & 0x7FF) - 1023;
long mantissa = bits & 0xFFFFFFFFFFFFFL;
long raw = (negative ? 1 : 0);
raw = (raw << 39) | (mantissa >> 13);
raw = (raw << 8) | ((exponent + 129) & 0xFF);
for (int k = 0; k < 6; k++)
{
r[k] = (byte)(raw & 0xFF);
raw >>= 8;
}
return r;
}
I don’t know C#, so I’m having a hard time translating it to Python. Can anyone help me? Or perhaps there is a better way?
I have found this but it seems to only convert 48‑bit Real
to double
, not the other way around as I need.
Let me try to translate the C# to python
1.- Convert the bits from a double number to a number (unsigned long long).
long bits = BitConverter.DoubleToInt64Bits(d);
translates to
struct.unpack("Q", struct.pack("d", python_double) )[0]
it uses the struct module from standard library.
2.- Extract each field from the double representation
bool negative = ((bits >> 63) & 1) != 0;
long exponent = ((bits >> 52) & 0x7FF) - 1023;
long mantissa = bits & 0xFFFFFFFFFFFFFL;
That can translated alsmot verbatim, since the same operators exist in python.
negative = ((bits >> 63) & 1) # Integer 1 for negative, 0 for positive
exponent = ((bits >> 52) & 0x7FF) - 1023
mantissa = bits & 0xFFFFFFFFFFFFF
3.- Pack again the number into 48 bits
long raw = (negative ? 1 : 0);
raw = (raw << 39) | (mantissa >> 13);
raw = (raw << 8) | ((exponent + 129) & 0xFF);
Same as number 2,
raw = negative
raw = (raw << 39) | (mantissa >> 13)
raw = (raw << 8) | ((exponent + 129) & 0xFF)
4.- Convert the number to a string of 6 bytes
for (int k = 0; k < 6; k++)
{
r[k] = (byte)(raw & 0xFF);
raw >>= 8;
}
Use struct as in step 1,
data = struct.pack('Q', raw)
data = data[:6] # Drop the 16 MSB
NOTE: I'm dropping the last 2 chars because struct uses the processors' endianness by default (x86 in my case), but that can be controlled with the first argument.
TIP: If you want to convert a number to a binary representation you could use '{:064b}'.format(number)
. This will pad it with zeros to fill 64 chars.