I am maintaining a program that takes data from a PDP-11 (emulated!) program and puts it into a modern Windows-based system. We are having problems with some of the data values being reported as "1.#QNAN" and also "1.#QNB". The customer has recently revealed that 'bad' values in the PDP-11 program are represented by 2 16-bit words with all the bits set except the first. I think that it is when we try to convert these to IEEE floats that we are getting the errors.
I have found the code below that is used for converting the PDP-11 values to IEEE. I am not very in touch with the intricacies of floating point representations but this seems a bit simple to me! Would this really reliably convert PDP-11 floats to IEEE?
// ---------------------------------------------------------------- cnvPDPfloat
// CNVPDPFLOAT
// ----------------------------------------------------------------------------
//
// Converts PDP11 float (two 16-bit words) into IEEE float
//
// PDP11 and IEEE floats have same layout so can be mapped onto eachother.
// But PDP11 exponent must have 2 subtracted for IEEE. Or just divide by 4.
//
float cnvPDPfloat( PDP11Float input )
{
union
{
unsigned long pdp11;
float ieee;
} uFloat;
uFloat.pdp11 = (input.word[0] << 16) + input.word[1];
return (uFloat.ieee / (float) 4.0);
}
--- Alistair.
The code doesn't check for undefined value, clean-zero and dirty-zero, but dividing by 4, discussed in other answers, is good. The OP probably knows it because they would spot if the result was always wrong. The exponent bias also confused me today, so I'll quote what I've just read in this fine document: Binary floats with hidden bit:
At first the hidden bit is given another position. IEEE assumes this bit before the fractional period and Digital assumes it immediately after that period. According to IEEE the visible part of the mantissa ('visman') starts immediately after the period, whilst according to Digital it starts behind the hidden bit. Thus the value range of the total mantissa is:
IEEE: 1.0 =< (1.visman) < 2.0 Digital: 0.5 =< (0.1 visman) < 1.0
At second the excess-biases in the notation of the exponent differ. [by 1 ...]
Both effects together make that the bit pattern in an IEEE- float represents a number four times in size of the value the same bit pattern in a Digital-float stands for.
This also explains why some references state that IEEE bias is 126.
From this page, the PDP-11 format is identical to IEEE-754 floating-point format except that the exponent is biased by 128 in PDP-11, whereas it is biased by 127 in IEEE-754. So, you need to divide by 2.0 and not 4.0. This doesn't take care of NaNs and infinities, but from my google searches, looks like PDP-11 didn't have those.
You will also have issues with overflow. The PDP format overflows earlier, but I am assuming that is OK since you can't really do anything once a number has already overflown.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With