xeruf
xeruf

Reputation: 3000

Java convert float to byte on custom terms

I want to write/read millions of numbers from 0-15 from/to a file. Precision is not an issue, as long as the read values are within +-0.1 of the written one, everything is fine.

Previous Ideas

My first, premature idea was to convert a float to a String like this and write them space-separated:

String.format("%.1f%s", float)

This, of course, is very inefficient, as it uses 4-5 bytes for every float.

Then I came to the idea to just write the bytes of each float, that would be faster but not sufficiently reduce the size.

ByteBuffer.allocate(4).putFloat(float).array()

Current issue

My current idea is to reduce the float to one byte. Looking at the ranges and precision I need, I would allocate the first 4 bits to represent the decimals before the floating point and the last 4 bits to the tail.

But how can I obtain these bits fast, since it has to be done millions of times?

Upvotes: 0

Views: 449

Answers (2)

Axel Kemper
Axel Kemper

Reputation: 11322

You might use something like this:

//  conversion factor to map 15.0 to 0xF0
float m = (float) (0xF0 / 15.0);

for (float x = 0.0f; x <= 15.0f; x += 0.25f) {
    //  obtain byte corresponding to float
    byte b = (byte) (m * x);
    //  recover float from byte to check conversion
    //  mask off sign bit to convert signed to unsigned byte
    float r = (b & 0x0FF) / m;
    //  what is the difference between original float and 
    //  recovered float?
    float error = Math.abs(x - r);
    //  show all values for testing
    String s = " b=0x" + Integer.toHexString(b & 0x0FF) + 
               " r=" + Float.toString(r) + 
               " err=" + Float.toString(error);
    System.out.println(s);
}

Upvotes: 0

Coderino Javarino
Coderino Javarino

Reputation: 2881

Since your tail is single digit, it can be implicit - i.e. 14.3 is converted to 143. To convert back, it would simply be 143 / 10 to get whole part, and 143 % 10 to get the fraction. Here is how an implementation could look like.

public class Test {

    public static void main(String[] args) {
        float floatValue = 14.1f;
        Test test = new Test();
        byte b = test.toByteStorage(floatValue);
        System.out.println(test.fromByteStorage(b));
    }

    byte toByteStorage(float f) {
        return (byte) (f * 10);
    }

    String fromByteStorage(byte b) {
        int intValue = Byte.toUnsignedInt(b);
        return intValue / 10 + "." + intValue % 10;
    }
}

Upvotes: 1

Related Questions