0

I am storing a long value comes from backend system and I had to convert it to float because of one of the third party api only understands float. Now when I read back the float and trying to convert back to long I am getting a bigger number(some times I've seen smaller as well)than what I had.

My question is how can I get back the original number in long. I am happy to add any rounding logic if required

public class Main {

    public static void main(String[] args) {


        long item = 1502028000;

        System.out.println(String.format("item -> %d",item));

        float floatItem = item;

        System.out.println(String.format("floatItem ->  %f",floatItem));

        long resultItem = (long)floatItem;

        System.out.println(String.format("resultItem ->  %d",resultItem));

    }
}

Below is the output. I need my original number back which is 1502028000 in this case.

item -> 1502028000
floatItem ->  1502028032.000000
resultItem ->  1502028032
10
  • 5
    You cannot long-float is a lossy conversion (also float-long). Commented Aug 11, 2017 at 6:09
  • Can you use double instead? Commented Aug 11, 2017 at 6:10
  • No only I have option of using float . I can't modify the third-party API. Can we do some Math.round or something to get the original number back Commented Aug 11, 2017 at 6:12
  • @Bulu No, you can't. Commented Aug 11, 2017 at 6:13
  • @GáborBakos Sure it would. Commented Aug 11, 2017 at 6:14

3 Answers 3

3

The short answer is that a float value is only precise to about 7 digits. In terms of the the long value you are converting to a float, that means the float can only retain the first 7 digits of 1502028000. Note those 7 are still retained in the float value and when when you convert back to a long.

If you would like to read more about float precision you should take a look at this. Just as an exercise, you could do the same thing with a double and more digits should be retained.

Sign up to request clarification or add additional context in comments.

1 Comment

A double only happens for the cases you are giving it but it would also break at some point. It's just has a higher precision because if is represented by 64 bits not 32 like a float
0

A float value only has ~24 significant bits, a long has 64 bits. So it must happen that some/many different long values are giving the same float value. And that can't be recovered.

You said that your longs always are multiples of 1000. So of the many longs that correspond to your given float, only those divisibe by 1000 are valid for you. That's what your rounding suggestion Math.round(value/1000)*1000 will use. But that only works until there are more than 1000 longs mapping to one float, and that happens around the 10 billion magnitude. Your example is just a factor of ten below that, so that won't help reliably if the numbers can grow.

If you REALLY MUST map back the float value to the original long (ask yourself: why is it necessary - can I do my job another way?), you might maintain a Map from Float values to the original Long values wherever you pass a long to the third-party library. IF the long values are sparse, there are chances that within the valid long values that you used, you can often map back from float without ambiguity.

But that's a nasty kludge. Be prepared to deal with the ambiguity if it arises.

1 Comment

While that is almost true (those ~24 significant bits), it is not the whole truth. The fact that floats have an exponent means that other values can also be represented, but not all of them. I would have pointed out that a float generally has 32 bits, so it is clear it can't have a different representation for every 64 bit value. Due to the way it is made up, it can also represent pretty large values, but not all of them accurately.
0

It appears that float doesn't have enough size to convert a "long" value and thus while converting, it looses it's precision.

To resolve this, you can use double instead of float. That will retain your value after the double conversion you are doing.

long item = 1502028000;
double floatItem = (double)item;
long resultItem = (long)floatItem;
System.out.println(String.format("resultItem ->  %d",resultItem));

This prints :

resultItem ->  1502028000

1 Comment

Even double won't be enough for the whole value range of long.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.