When writing a converter tool for a binary file format, I had problems reading some of the floating point numbers. After a little bit of research I found out that this very special format was used in programs written in Borland Pascal/Delphi. Since I couldn't find any Java class that's able to read this kind of number I wrote it myself.
As far as I remember these are basically reverse IEEE floating point numbers of six bytes. (It's been a while since I wrote this. See the PDF file by Richard Biffl for a detailed description of the format.)
References:
And here is the code:
package de.tilman.util;
import java.math.BigDecimal;
/**
* A class for representation and conversion of 6-byte/48-bit floating
* point numbers used in Borland Pascal/Delphi.
*
* @author Tilman Walther
*/
public class Real48
{
char[] bytes
;
double value
;
/**
* Represents a number in Real48 format.
*
* @param bytes the byte values of the number
*/
public Real48
(char[] bytes
) {
this.
bytes = bytes
;
this.
value = Real48.
getDoubleFromBytes(bytes
);
}
/**
* Returns the value of the number as double.
*
* @return the number as double
*/
public double getDoubleValue
() {
return value
;
}
/**
* Returns the byte values of the Real48 as char[].
*
* @return the byte values
*/
public char[] getBytes
() {
return bytes
;
}
/**
* Converts a Real48 in a double.
*
* @param bytes the number in Real48 format
* @return the number as double
*/
public static double getDoubleFromBytes
(char[] bytes
) {
long[] real48
= new long[6];
real48
[0] = bytes
[0];
real48
[1] = bytes
[1];
real48
[2] = bytes
[2];
real48
[3] = bytes
[3];
real48
[4] = bytes
[4];
real48
[5] = bytes
[5];
// get sign
long sign
= (real48
[0] & 0x80
) >> 7;
// get significand
long significand
= ((real48
[0] % 0x80
) << 32)
+ (real48
[1] << 24)
+ (real48
[2] << 16)
+ (real48
[3] << 8)
+ (real48
[4]);
// get exponent
long exponent
= bytes
[5];
// if the exponent is zero the real represents zero, too
if (exponent
== 0) {
return 0.0;
}
// convert exponent (bias for Real48 is 129, bias for IEEE 754-double is 1023)
exponent
+= 894;
long bits
= (sign
<< 63) + (exponent
<< 52) + (significand
<< 13);
double value
= Double.
longBitsToDouble(bits
);
// since Real48 has only a precision of 11 we need to set all digits > 11 to zero
BigDecimal bd
= new BigDecimal(value
);
bd
= bd.
setScale(11,
BigDecimal.
ROUND_DOWN);
return bd.
doubleValue();
}
}