I am writing a program that takes raw double values from a database and converts them to 8-byte hex strings, but I don't know how to prevent loss of precision. The data recieved from all devices are stored as doubles, including the 8-byte identification values.
Instances of doubles such as 7.2340172821234e+16 parse correctly without loss of precision, where the exponent is 10^16.
However, in instances where the exponent is 10^17, Java loses precision. For example, 2.88512954935019e+17 is interpreted by Java as 1.44464854248327008E17
The code I am using looks like this:
public Foo(double bar) {
this.barString = Long.toHexString((long) bar);
if (barString.length == 15) {
barString = "0" + barString; //to account for leading zeroes lost on data entry
}
}
I am using a test case similar to this to test it:
@Test
public void testFooConstructor() {
OtherClass other = new OtherClass();
OtherClass.Foo test0 = other.new Foo(72340172821234000d); //7.2340172821234e+16
assertEquals("0101010100000150", test0.barString); //This test passes
OtherClass.Foo test1 = other.new Foo(144464854248327000d);//1.44464854248327e+17
assertEquals("02013e0500000758, test1.barString); //This test fails
}
The unit test states:
Expected: 02013e0500000758
Actual: 02013e0500000760
When I print out the values that Java stored 72340172821234000d and 144464854248327000d as it respectively prints:
7.2340172821234E16
1.44464854248327008E17
The latter value is off by 8, which seems to be consistent for the few that I have tested.
Is there anything I can do to correct this error?
EDIT: This is not a problem where I care about what is past the ones place. The question that some think this is a duplicate of is asking why floating point numbers are less precise, I am asking how to avoid the loss of precision, through similar workarounds to those that Roman Puchkovskiy suggested.