Link to home
Start Free TrialLog in
Avatar of chrisjarram
chrisjarram

asked on

converting float to short

Hi,
Does anyone know a *fast* way of converting a float to a short so that it can be converted back to its original float value later on (minus some precision, obviously).  I want to be able to store values of up to 99.99, with the point fixed in this place.  Currently I am using string concatenation tricks (e.g. toString and intValue() on single bytes) but would rather do this mathematically somehow because speed is totally of the essence in this project! (I am working with streaming animations).

Thanks very much in advance for any help anyone can give,

Chris
Avatar of shlomoy
shlomoy

what's the precision required?

do you want to have an int at the end?
Avatar of chrisjarram

ASKER

Hi,
As mentioned in the question, I want to be able to store values of up to 99.99 (so need to retain 2dp precision).  The point is that I am streaming floating point values down a low-bandwidth link, but they are never over +/- 99.99, so obviously using 32-bits per fp is hugely wasteful of transfer time.  If I squash floats down to 16 bits I can halve the transfer time for these values.

The method I am currently using is as follows:

At server end:
1) convert float to text
2) read the numbers preceding the decimal point (this number is never greater than +/- 99) and store this value in a byte (byte1)
3) read the first 2 digits after the decimal point (e.g. .26) and store this value in another byte (byte2)

At client end:
1) concatenating a string using byte1 + '.' + byte2
2) convert this string back to a float using Float.valueOf(string).floatValue()
(the number has to be converted back to a float at the client end before I can use it).

I am currently working with 10's of thousands of values per second, so obviously this conversion for every single one is extremely time consuming (using the method I am using).  This way is not simple because there are certain issues like not being able to store -0 in a byte (so when for example the number -0.23 occurs at the server side, I am having to store byte1 as 127 as a workaround (and then at the client end I check for this value and if it occurs reconstruct the float as -0.xx)

There must be a faster way than having to do this with strings!

Thanks very much for the response, hope u can help :)

Chris
I think the best is to cast your float to short and back  
similar to this

    public Float F = new Float(456.2355);
    f = F.floatValue();
    s = F.shortValue();

or like this:

    float ff = (float)456.2355;
    short ss = (short)ff;

does this help?
Hi HiThere,

I really wish it was that simple!Unfortunately, using this method you obviously lose the numbers trailing the decimal.  When doing a straightforard cast like this a floating point value is rounded to an integer value.  The answer must lie in an fp exponent / mantissa analysis and conversion and I wondered if anyone knew of a JAVA library that contains a method that can do this for small fp values, or if anyone could give me a code snippet of a matematical way (ie binary level) of converting these values.

Thanks anyway,
Chris
check out the article about the JVM floating point arithmetic.
maybe this can help you:
http://www.javaworld.com/javaworld/jw-10-1996/jw-10-hood.html
float f=(float)1234.5678;
      
// convert to short using fixed point
short s=(short)(f*100.0);
      
// convert to float using fixed point
float g=((float)s)/(float)100.0;

regards,
Mike.

sorry don't try that - it doesn't work.
Mike.
This sort of thing may be quicker...

float f = 25.32;
int tempInt1 = (int)f; //tempInt1 = 25
int tempInt2 = (int)f * 100; //tempInt2 = 2532

byte b1 = (byte) tempInt1; // b1 = 25
byte b2 = (byte) (tempInt2 - (tempInt1*100)); //b2 = 32

It will be quicker if you declare all your variables first and then just use them in a loop.

Putting the conversion in a method will slow it down as well so do it in line, such as:

//initialise...
float f = 25.32;
int tempInt1;
int tempInt2;
byte b1;
byte b2;

//loop for each float....
      tempInt1 = (int)f; //tempInt1 = 25
      tempInt2 = (int)f * 100; //tempInt2 = 2532

      b1 = (byte) tempInt1; // b1 = 25
      b2 = (byte) (tempInt2 - (tempInt1*100)); //b2 = 32
//end loop...

As you can see, this will work by justusing basic mathematical functions. As long as the float number is never greater than 99.99 this will work OK.

It gets the exponent part of the float as two digits here:

  int tempInt1 = (int)f; //tempInt1 = 25

and converts them straight to an int losing the mantissa. You can also then copy this into your first byte, b1.

Then it gets the mantissa by multiplying the original float by 100 so that

  25.32 x 100 = 2532

and store this in tempInt2 as 2532.

Now if you take the int value in tempInt1 (which is 25) and multiply this also by 100 you get 2500.

Finally, take tempInt1 from tempInt2 you get

  2532 - 2500 = 32

this is the number to store in your second byte b2.
ASKER CERTIFIED SOLUTION
Avatar of Jod
Jod

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks Jod!

I can't beleive I didn't think of this(I have a BSc Hons in computer science!):-  It was exactly the answer I was looking for.

Sorry everyone else...

Chris