4

So I'm trying to divide two BigIntegers 22 and 7. In other words, I'm trying to store the first few decimals of b1.divide(b2) [where b1 = new BigInteger("22"), and b2 = new BigInteger("7")] into some datatype. However, if I use a BigDecimal, it shows an irrepresentable number error, while it doesn't even work for doubles. What should I do? For your convenience, here's the code:

BigInteger b1 = new BigInteger("22");
BigInteger b2 = new BigInteger("7");
BigInteger b3 = b1.divide(b2);
System.out.println(b3);

And here's what shows up in the console:

Exception in thread "main" java.lang.ArithmeticException: Non-terminating decima
l expansion; no exact representable decimal result.
    at java.math.BigDecimal.divide(Unknown Source)
    at Divider.main(Divider.java:13)
Sabir Khan
  • 9,826
  • 7
  • 45
  • 98
Rapid Readers
  • 303
  • 1
  • 3
  • 13

8 Answers8

12

Using BigInteger.divide(...) will give BigInteger only, so you will loose the precision of the output if you use this method directly. Below are some solutions.

Solution 1 (using BigInteger):

    BigInteger b1 = new BigInteger("22");
    BigInteger b2 = new BigInteger("7");
    double d = b1.doubleValue() / b2.doubleValue();
    System.out.println(d);

Solution 2 (using BigDecimal, already defined precision)

    BigDecimal b1 = new BigDecimal("22");
    BigDecimal b2 = new BigDecimal("7");
    BigDecimal b3 = b1.divide(b2, MathContext.DECIMAL32);
    System.out.println(b3);

Solution 3 (using BigDecimal, self controlled precision)

Refer solution given by Jason Hoetger

Amber Beriwal
  • 1,568
  • 16
  • 30
  • If `b2` is much larger than `b1`, `b1.doubleValue() / b2.doubleValue()` will return 0 much sooner than if you do the division on the big integers (in a way that understands big integer division) before converting the result to a double. – Boris Verkhovskiy Feb 02 '21 at 14:36
2

BigInteger.divide() returns a BigInteger, so you're not going to be able to get "the first few decimals" of any result of BigInteger.divide() unless it is actually an integer.

If b1 and b2 absolutely must be BigIntegers, you can create a BigDecimal from your BigInteger, then use BigDecimal.divide(). You'll need specify the scale of the result in order to control the number of decimal places, as well as a MathContext to determine how to round the answer. For example:

BigInteger b1 = new BigInteger("22");
BigInteger b2 = new BigInteger("7");
BigDecimal quotient = new BigDecimal(b1)
    .divide(new BigDecimal(b2), 3, RoundingMode.HALF_EVEN);
System.out.println(quotient);

Results in:

3.143
Jason Hoetger
  • 7,543
  • 2
  • 16
  • 18
0

If I understand you correctly, you're trying to divide BigInteger b1 by b2 and store it in a BigInteger. However, the quotient of two integers is an integer.

3.14286 (rounded) is not an integer.

You can use BigDecimal instead:

BigInteger b1 = new BigInteger("22");
BigInteger b2 = new BigInteger("7");
BigDecimal b3 = new BigDecimal(b1.divide((double)b2));
System.out.println(b3);
Justin Singh-M.
  • 378
  • 2
  • 8
0

BigInteger's divide method returns a BigInteger whose value is {@code (this / val)}.Y

marlon
  • 1
  • 1
0

Assuming that you are indeed using BigDecimal (and not BigInteger): A BigDecimal is meant to provide a precise decimal value in a way that floating point cannot. However, when dividing 22/7, that has a repeating decimal and thus cannot be represented as-is in a BigDecimal.

In this case, you need to specify to how many decimal places you wish to round, and how you wish to round (up, down, or nearest). So to round to three decimal places, you will want:

BigDecimal b3 = b1.divide(b2, 3, RoundingMode.HALF_EVEN);
Scary Wombat
  • 44,617
  • 6
  • 35
  • 64
Joe C
  • 15,324
  • 8
  • 38
  • 50
0

The error you were seeing for BigDecimal is explained well here: ArithmeticException: "Non-terminating decimal expansion; no exact representable decimal result"

By adding precision and rounding off, the issue can be handled. a.divide(b, 2, RoundingMode.HALF_UP) where 2 is precision and RoundingMode.HALF_UP is rounding mode. https://docs.oracle.com/javase/7/docs/api/java/math/RoundingMode.html

Your current code with BigIntegers works on Java7.

And to save the result in a double for both BigDecimal and BigInteger:

double b4 = b1.divide(b2,2).doubleValue();
double b4 = b1.divide(b2).doubleValue();

So, BigDecimal:

BigDecimal b1 = new BigDecimal("22");
BigDecimal b2 = new BigDecimal("7");
BigDecimal b3 = b1.divide(b2,2,RoundingMode.HALF_UP);
double b4 = b1.divide(b2,2).doubleValue();
double b5 = b1.divide(b2,2,RoundingMode.HALF_UP).doubleValue();

BigInteger:

 BigInteger b1 = new BigInteger("22");
 BigInteger b2 = new BigInteger("7");
 BigInteger b3 = b1.divide(b2);
 double b4 = b1.divide(b2).doubleValue();
Community
  • 1
  • 1
Sid
  • 408
  • 4
  • 7
-1

Since big integers are thought for BIG NUMBERS dont use double (maybe it too big for 64 bits space...) instead use BigDecimal which can take in the constructor a BigInteger too:

BigDecimal b3 = new BigDecimal("22").divide(new BigDecimal("7"), 3, RoundingMode.HALF_EVEN);

System.out.println(b3);

ΦXocę 웃 Пepeúpa ツ
  • 47,427
  • 17
  • 69
  • 97
-1

Here is how to get double value,

BigInteger b1 = new BigInteger("22");
BigInteger b2 = new BigInteger("7");
double b3 = b1.divide(b2).doubleValue();
System.out.println(b3);
Md Samiul Alim Sakib
  • 1,114
  • 12
  • 15