How to do a fractional power on BigDecimal in Java?
The solution for arguments under 1.7976931348623157E308 (Double.MAX_VALUE) but supporting results with MILLIONS of digits:
Since double supports numbers up to MAX_VALUE (for example, 100! in double looks like this: 9.332621544394415E157), there is no problem to use BigDecimal.doubleValue(). But you shouldn't just do Math.pow(double, double) because if the result is bigger than MAX_VALUE you will just get infinity. SO: use the formula X^(A+B)=X^A*X^B to separate the calculation to TWO powers, the big, using BigDecimal.pow, and the small (remainder of the 2nd argument), using Math.pow, then multiply. X will be copied to DOUBLE - make sure it's not bigger than MAX_VALUE, A will be INT (maximum 2147483647 but the BigDecimal.pow doesn't support integers more than a billion anyway), and B will be double, always less than 1. This way you can do the following (ignore my private constants etc):
int signOf2 = n2.signum();
try {
// Perform X^(A+B)=X^A*X^B (B = remainder)
double dn1 = n1.doubleValue();
// Compare the same row of digits according to context
if (!CalculatorUtils.isEqual(n1, dn1))
throw new Exception(); // Cannot convert n1 to double
n2 = n2.multiply(new BigDecimal(signOf2)); // n2 is now positive
BigDecimal remainderOf2 = n2.remainder(BigDecimal.ONE);
BigDecimal n2IntPart = n2.subtract(remainderOf2);
// Calculate big part of the power using context -
// bigger range and performance but lower accuracy
BigDecimal intPow = n1.pow(n2IntPart.intValueExact(),
CalculatorConstants.DEFAULT_CONTEXT);
BigDecimal doublePow =
new BigDecimal(Math.pow(dn1, remainderOf2.doubleValue()));
result = intPow.multiply(doublePow);
} catch (Exception e) {
if (e instanceof CalculatorException)
throw (CalculatorException) e;
throw new CalculatorException(
CalculatorConstants.Errors.UNSUPPORTED_NUMBER_ +
"power!");
}
// Fix negative power
if (signOf2 == -1)
result = BigDecimal.ONE.divide(result, CalculatorConstants.BIG_SCALE,
RoundingMode.HALF_UP);
Results examples:
50!^10! = 12.50911317862076252364259*10^233996181
50!^0.06 = 7395.788659356498101260513
Java's BigDecimal.power(BigDecimal exponent): Is there a Java library that does it?
There is a Math.BigDecimal implementation of core mathematical functions with source code available from the Cornell University Library here (also you can download the library as a tar.gz). Here is a sample of the library use:
import org.nevec.rjm.*;
import java.math.BigDecimal;
public class test {
public static void main(String... args) {
BigDecimal a = new BigDecimal("1.21");
BigDecimal b = new BigDecimal("0.5");
System.out.println(BigDecimalMath.pow(a, b).toString());
}
}
Prints out:
1.1
Update
The license information is now clear in the May 2015 update:
The full source code is made available under the LGPL v3.0.
Recurring fraction to decimal on BigDecimal
Let split the problem in two pieces:
- Convert
1/0.3
toN/M
form - Convert
N/M
toa.b(c)
form
Lets convert 0.3
to M/N
form (which give us 3/10
).
String input = "123.456";
String[] parts = input.split("\\.");
String whole = parts[0];
String fraction = parts[1];
int wholeInt = Integer.parseInt(whole);
int fractionInt = Integer.parseInt(fraction);
int multiplier = pow10(fraction.length());
int n = wholeInt * multiplier + fractionInt;
int m = multiplier;
System.out.println(n + "/" + m);
I used function pow10
which simply returns 10 power input.
Now we need divide 1
by 10/3
it is easy N1/M1
divided by N2/M2
it is simply (N1*M2)/(N2*M1)
.
We get our result in form N/M
now (we also need to normalize it by dividing both part by GCD(N, M
)
Now we ready to solve main problem.
First of all get whole part
int whole = n/m;
then find fraction and repeating part
int current = n%m;
StringBuilder sb = new StringBuilder();
List<Integer> controlSet = new ArrayList<>();
while((!controlSet.contains(current))){
int currentDigit = current *10 / m;
sb.append(currentDigit);
controlSet.add(current);
current = current *10 - m * currentDigit;
}
String fraction = sb.toString().substring(0, controlSet.indexOf(current));
String repeat = sb.toString().substring(controlSet.indexOf(current));
Here we just divide in loop getting result number by number.
Main trick then number starts to repeat when we meet current
that we already use.
Now you need to take all parts together. Implement GCD
(lots of implementation over internet).
How do I get whole and fractional parts from double in JSP/Java?
http://www.java2s.com/Code/Java/Data-Type/Obtainingtheintegerandfractionalparts.htm
double num;
long iPart;
double fPart;
// Get user input
num = 2.3d;
iPart = (long) num;
fPart = num - iPart;
System.out.println("Integer part = " + iPart);
System.out.println("Fractional part = " + fPart);
Outputs:
Integer part = 2
Fractional part = 0.2999999999999998
Related Topics
Raising a Number to a Power in Java
How to Read Properties File in Web Application
Why Doesn't a Missing Annotation Cause a Classnotfoundexception at Runtime
How to List All Classes Loaded in a Specific Class Loader
How to Tune Tomcat 5.5 Jvm Memory Settings Without Using the Configuration Program
Selenium Webdriver + Java - Eclipse: Java.Lang.Noclassdeffounderror
Java.Lang.Noclassdeffounderror: Org/Hamcrest/Selfdescribing
Class Not Found with Ant, Ivy and Junit - Error in Build.Xml
Java: What's the Big-O Time of Declaring an Array of Size N
Is There a MACro Recorder for Eclipse
Parallel Streams, Collectors and Thread Safety
Using Javamail to Connect to Gmail Smtp Server Ignores Specified Port and Tries to Use 25
Tomcat 8 Is Not Able to Handle Get Request with '|' in Query Parameters
Must Spring Component Classes Be Thread-Safe
Is There a Newline Constant Defined in Java Like Environment.Newline in C#
How to Add an Extra Source Directory for Maven to Compile and Include in the Build Jar