0

I need advice how to properly convert negative fractional part to binary. My custom data type with fixed point need be converted to byte[]. So, currently I need to implement such conversion:

BigDecimal -> byte[] -> BigDecimal

As I understand, fraction follows the same 2's complement form as an integer part, right? How one can distinquish "plain -1" from negative fraction? Short generic case example would be very usefull.

How one will write -1.375 and -0.375 in binary ?

Constantine
  • 1,802
  • 3
  • 23
  • 37
  • 2
    Why? Is it necessary? This looks like a XY Problem... – AxelH Dec 27 '16 at 12:32
  • Yeap, it is necessary. – Constantine Dec 27 '16 at 12:47
  • Let's assume that you really need to use a byte[] ... don't see the needs here (it is serialisable you know) but you probably could find your answer [here](http://stackoverflow.com/questions/6167697/how-to-convert-java-bigdecimal-to-normal-byte-array-not-2s-complement) – AxelH Dec 27 '16 at 12:52
  • I am a bit unclear what you want -13.456 to -0.456 maybe to -456 E-3? – Joop Eggen Dec 27 '16 at 13:17
  • I just need to understand how to properly convert negative fraction to binary. Java, BigDecimal or whatever are not the case. I developing ABI, so binary form should be unbound from any implementation. – Constantine Dec 27 '16 at 22:52
  • `unscaledValue().toByteArray()` and `scale()` are implementation independent, and so are their results. They produce well defined values. That can be used for an ABI. – Rudy Velthuis Dec 28 '16 at 13:13

1 Answers1

0

I think you can code as (updated):

Convert to byte[]

    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    DataOutputStream dos = new DataOutputStream(bos);
    BigDecimal d = BigDecimal.valueOf(-0.00390625);
    dos.writeInt(d.scale());
    dos.write(d.unscaledValue().toByteArray());
    dos.close(); // flush
    byte[] array = bos.toByteArray();

Convert from byte[]

    ByteArrayInputStream bis = new ByteArrayInputStream(array);
    DataInputStream dis = new DataInputStream(bis);
    int sc = dis.readInt(); //grab 4 bytes
    BigInteger unscaledVal = new BigInteger(Arrays.copyOfRange(array, 4, array.length));
    System.out.println(new BigDecimal(unscaledVal, sc));

Note: probably you would like to save BigDecimal array length.

krzydyn
  • 1,012
  • 9
  • 19
  • It actualy gives me wrong result: for -0.00390625 (least negative for 8 bit fraction) convertion returns 0.16386591 Just can't find clear algorithm how to handle negative fractions. I can feel it is exists) – Constantine Dec 27 '16 at 12:56
  • See my update. We need also `scale` to correctly recover `BigDecimal` – krzydyn Dec 27 '16 at 13:14
  • because unscaledValue just do `bd.value * 10 ^ bd.scale`. – AxelH Dec 27 '16 at 13:26
  • Thanks for trying, but it's not what I am actualy looking for. Am developing ABI, so binary form of my datatype should be unbound from any technology. – Constantine Dec 27 '16 at 23:21
  • There is no technology - I have to put into byte buffer to components which are part of `BigDecimal`: the scale and the unscaled value. – krzydyn Dec 28 '16 at 12:32