0

I read here and there explanations about how to deal with big numbers and it seems that the same class BigNumber can also be used for very small numbers.

However I cannot figure out how to make it work without losing precision.

I have numbers like 0.0000000000012 that I want to use in an equation but I dont know how to create this number with BigNumber (if that is wwhat I should use) and then how to avoid to lose precision when i turn it into a double to use in my equation.

Should I put every number used in hte equation as a BigDecimal (even the one with simple values(12, 0.1,...) or only 0.0000000000012 should be a BigNumber and I can be sure I wont lose precision?

Thank you in advance for your help, Regards, B.

om-nom-nom
  • 60,231
  • 11
  • 174
  • 223
user2501025
  • 75
  • 1
  • 5
  • 4
    I'm not aware of a BigNumber class. There's BigDecimal and BigInteger, but not BigNumber. It sounds like you should be using BigDecimal everywhere though... and *don't* turn it into a double. – Jon Skeet Jun 19 '13 at 12:20
  • 1
    Use BigDecimal. this will give you the functionality to transform value to double value. – Ashish Aggarwal Jun 19 '13 at 12:27

3 Answers3

4

Use the class BigDecimal. It can be used to represent decimal numbers of arbitrary precision. To create a BigDecimal from a literal which is too precise to be represented by a double, use the string constructor:

BigDecimal almostOne = new BigDecimal("0.999999999999999999999999999999999999999987", MathContext.UNLIMITED);

When you convert them into doubles you lose precision. Therefor the BigDecimal class has various methods to perform basic arithmetics while retaining precision:

BigDecimal exactlyTen = new BigDecimal(10);
BigDecimal almostTen = almostOne.multiply(exactlyTen);

When your code is performance-critical, I recommend the question "What to do with Java BigDecimal performance?" as further reading.

Community
  • 1
  • 1
Philipp
  • 60,671
  • 9
  • 107
  • 141
3
String number = "0.0000000000012";

BigDecimal decimal = new BigDecimal(number);
System.out.println(decimal.toString());
decimal = decimal.multiply(new BigDecimal(1000000000000L));
System.out.println(decimal.toString());

here is the code how you can use and test BigDecimal Number run this code. Fir sysout will return 1.2E-12 which is eq to 0.0000000000012. To test this multiply this with 1000000000000 result to 1.2. that means you won't lose your precision.

Bill the Lizard
  • 369,957
  • 201
  • 546
  • 842
Ashish Aggarwal
  • 2,950
  • 2
  • 21
  • 43
0

You don't have to use BigDecimal unless you have more than 15 significant digits of precision. You do have to use appropriate rounding which is something BigDecimal helps you with but it doesn't mean you can't do the same with double.

double d = 0.0000000000012;
BigDecimal bd = BigDecimal.valueOf(d);
System.out.println("before d: " + d + " bd: " + bd);
d *= 1000000000000L;
d = Math.round(d * 1e2) / 1e2; // round to two places
bd = bd.multiply(BigDecimal.valueOf(1000000000000L));
System.out.println("after d: " + d + " bd: " + bd);

prints

before d: 1.2E-12 bd: 1.2E-12
after d: 1.2 bd: 1.2000000000000

In terms of performance double out performs BigDecimal by a factor of 100x. BigDecimal also creates lots of garbage whereas double doesn't produce any. Creating lots of garbage is not only slow but slows down all the rest of your code by filling your CPU caches with garbage.

how to avoid to lose precision when i turn it into a double to use in my equation.

With double you need to keep track of the precision yourself. This is only a problem if you have functions which have no idea of the precision and you cannot tell them and need to pass on the value. i.e. you have no chance of rounding the answer.

Peter Lawrey
  • 498,481
  • 72
  • 700
  • 1,075