Reputation: 49
I have a binary file that contains 10-bit fixed point values that I need to convert to Java float
. I'm almost certain that the "format" is x.xxxxxxxxx
, where x is a bit. And I do think I understand the basics of doing this by hand.
I would have to do to the bits: x + 0.5*x + 0,25*x...
etc. For example
1010110010 = 1×1 + 0×½ + 1×¼ + 0×⅛ + 1×¹⁄₁₆ + 1×¹⁄₃₂...
But I have no idea how to do this in Java. I can read the file only one BYTE at a time, one value would be reading 2 bytes = 16 bits.
The file is in LITTLE ENDIAN.
Upvotes: 1
Views: 1020
Reputation: 41942
Alternatively just construct the float directly from the raw bits
Assuming the binary value is read into the low 10 bits of v
if (v == 0)
return 0.0f;
// shift the mantissa to the correct position and drop the implicit 1 bit
int mantissa = (v << (23 - Integer.highestOneBit(v))) & 0x7ffff;
int exponent = (-9 + 127) << 23;
return Float.intBitsToFloat(mantissa | exponent);
Upvotes: 0
Reputation: 109593
The conversion from bytes to 10-bit raw ints could be like this:
Path file = Paths.get("....");
byte[] data = Files.readAllBytes(file);
// data is a sequence of 10 bit fixed-point floats
if (data.length % 5 != 0) {
throw new IllegalArgumentException(
"File length is not a multiple of 10 bits: " + file);
}
int bitCount = data.length * 8;
bitCount = bitCount - (bitCount % 10); // When without check.
int[] rawInts = new int[bitCount / 10];
for (int bitIx = 0; bitIx < bitCount; bitIx += 10) {
int byteIx0 = bitIx / 8;
int byte0 = data[byteIx0) & 0xFF;
int byteIx1 = byteIx0 + 1;
int byte1 = data[byteIx1) & 0xFF;
int off = bitIx % 8;
int rawInt = ((byte0 << off + 2) & 0x3FF)
| (byte1 >> (8 - (2 + off));
rawInts[bitIx / 10] = rawInt;
}
Now to the fixed point format: with 10 bits one has 210 numbers, hence 0 .. 1023. This suggests that the fixed point is based around 1000, maybe 9.99
int integralPart = rawInt / 100;
int decimals = rawInt % 100;
P.S. not tested the bit shifting, which by the way could also be little endian.
Upvotes: 0
Reputation: 47739
If you have 10 bits, and the "binary point" is between the first and second bits, that just means the number is divided by 2 to the 9th, or 512. So put the value in the low end of an int, cast to float, divide by 512, and you have your number.
float finalAnswer = bitsInLowOrderEndOfInt / 512.0;
Upvotes: 2
Reputation: 533710
Instead of computing each bit, it is more efficient to calculate the exponent.
public double parse (InputStream is) {
long value = 0, factor = 0;
for(;;) {
int ch = is.read();
if (ch == '.') {
factor = 1;
} else if(ch == '0' || ch = '1') {
factor *= 2;
value = value * 2 + ch - '0';
} else {
break;
}
}
return factor == 0 ? value : (double) value / factor;
}
Upvotes: 1
Reputation: 8390
I would have to do to the bits: x,0.5*x+0.25*x.... etc.
That's actually not difficult in Java. Assuming you converted the bits into boolean
s, your code can look like this:
public double parse (boolean ... bits)
{
double val = (bits[0] ? 1 : 0); // note to check that bits[0] exists
for (int i = 1; i < bits.length; i++)
val += (1.0 / 2*i) * (bits[i] ? 1 : 0) * Math.pow(2, -1*i);
return val;
}
Upvotes: 0