2

I'm working with hex values and I need to retain the sign of the values. I'm wondering if someone has a creative way to retain the sign of the int without using BigInteger? I can't use BigInteger because it's not in my library due to size limitations; my program runs in an embedded environment.

I have a string of hex values as follows: 55844d000000000080027d801cf6380006f416c0c23d3e4000000000

    String          ssumI = null;
    String          ssumQ = null;
    String          sazI   = null;
    float           isumI = 0;
    float           isumQ = 0;
    float           iazI  = 0;

    ssumI = data.substring(0,8); 
    isumI = (float)(Integer.parseInt(ssumI, 16)/Math.pow(2,bits));
    //55844d00 parses fine

    ssumQ = data.substring(8,16); 
    isumQ = (float)(Integer.parseInt(ssumQ, 16)/Math.pow(2,bits));
    //00000000 parses fine

    sazI = data.substring(16, 24); 
    iazI = (float)(Integer.parseInt(sazI, 16)/Math.pow(2,bits));
    //80027d80 fails - NumberFormatException
    //should be -1,036,173,760 and in the int range

Am I not understanding the failure correctly? It seems like the failure is due to the sign bit being set.

Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
txcotrader
  • 585
  • 1
  • 6
  • 21
  • 3
    BigInteger is the obvious solution here - so why don't you use it? – Jon Skeet Mar 20 '15 at 08:11
  • It's not in my library due to size limitations, my program runs in an embedded environment – txcotrader Mar 20 '15 at 08:16
  • 2
    Right, so you should put that in your question. Any time the obvious solution is inappropriate because you're in an unusual context, you should explain that context. – Jon Skeet Mar 20 '15 at 08:17
  • unless bits is a floating-point value or larger than 31, use `1 << bits` instead of `Math.pow(2,bits)` – phuclv Mar 20 '15 at 08:52

2 Answers2

3

If you want to store 32 bits at a time, the obvious solution in my view would be to parse with Long.parseLong instead:

isumI = (float)(Long.parseLong(ssumI, 16) / Math.pow(2, bits));

(Do you definitely want to hold these values as float though? You're losing information that way...)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
0

If Java 8 is available you can use the new unsigned operations in it (How to use the unsigned integer in java 8?).

isumI = (float)(Integer.parseUnsignedInt(ssumI, 16)/Math.pow(2,bits));

But since each string has 32 bits, I suppose bits is less than 32. In that case you can rewrite it as

isumI = Integer.parseUnsignedInt(ssumI, 16)/(float)(1 << bits);

If bits can be larger than 32 (but less than 64), replace 1 by 1L

Also, notice that bits is unchanged in your function, you should replace Math.pow(2, bits) with 1 << bits and store it in a separate variable instead of recalculating it again and again.

Anyway if you intend to use the string as a big value then you should store it in an int array. A float has only 24 bits of significand and you may lose the low 8 bits if the value is large.

phuclv
  • 37,963
  • 15
  • 156
  • 475