Power to n implementation that produces wrong results for negative exponent - java

In the following (naive) implementation of a pow(x, n) method, ignoring completely any optimized approach, I find the following problem:
public double pow(double x, int n) {
boolean negative = n < 0;
long power = Math.abs(n);
double ans = 1.0;
for(long i = 0; i < power; i++) {
ans = ans * x;
}
return negative ? 1.0/ans: ans;
}
Here I have made the assumption that for the case of negative exponent I simply calculate the x^n and then return 1/(x^n) since e.g. 2^(-3) = 1/(2^3)
Problem:
The code fails in the following case:
pow(2.00000, -2147483648)
The output is 1.00000 while the expected correct result is 0.00000
If I change the code as follows:
public double pow(double x, int n) {
long power = n;
if(power < 0) {
x = 1 / x;
power = -power;
}
double ans = 1.0;
for(long i = 0; i < power; i++) {
ans = ans * x;
}
return ans;
}
The result is correct!
So what is the difference between doing the approaches? I was expecting them to be equivalent but they are not

Math.abs(n) is still an int, and only afterwards it is assigned to a long, Therefore, the absolute value of -2147483648 was -2147483648 again (this is noted in the documentation of Math.abs(int)). With the negative bound, the loop performed no iterations.
Math.abs((long)n) would work around that issue.

Related

Issues with accuracy with Bernoulli Number generator in java

I've created some code that generates the Bernoulli Numbers based off of formula 33 on MathWorld. This is given at https://mathworld.wolfram.com/BernoulliNumber.html and should work for all integers n but it diverges from the expected results extremely quickly once it gets to n=14. I think the issue may be in the factorial code, although I have no idea.
It's pretty accurate up until 13, all odd numbers should be 0 besides 1 but the values past 14 give weird values. For instance 14 gives a number like 0.9 when it should give something around 7/6 and say 22 gives a very negative number in the order of 10^-4. The odd numbers give strange values like 15 gives around -11.
Here is all the related code
public static double bernoulliNumber2(int n) {
double bernoulliN = 0;
for (double k = 0D; k <= n; k++) {
bernoulliN += sum2(k,n)/(k+1);
}
return bernoulliN;
}
public static double sum2(double k, int n) {
double result = 0;
for (double v = 0D; v <= k; v++) {
result += Math.pow(-1, v) * MathUtils.nCr((int) k,(int) v) * Math.pow(v, n);
}
return result;
}
public static double nCr(int n, int r) {
return Factorial.factorial(n) / (Factorial.factorial(n - r) * Factorial.factorial(r));
}
public static double factorial(int n) {
if (n == 0) return 1;
else return (n * factorial(n-1));
}
Thank you in advance.
The problem here is that floating point arithmetic doesn't need to overflow to experience catastrophic loss of precision.
A floating point number has a mantissa and an exponent, where the value of the number is mantissa * 10^exponent (real floating point numbers use binary, I'm using decimal). The mantissa has limited precision.
When we add floating point numbers of different signs we can end up with a final result which has lost precision.
e.g. let's say the mantissa is 4 digits.
If we add:
1.001 x 10^3 + 1.000 x 10^4 - 1.000 x 10^4
we expect to get 1.001 x 10^3.
But 1.001 x 10^3 + 1.000 x 10^4 = 11.001 x 10^3, which is represented as 1.100 x 10^4, given that our mantissa has only 4 digits.
So when we subtract 1.000 x 10^4 we get 0.100 x 10^4, which is represented as 1.000 x 10^3 rather than 1.001 x 10^3.
Here's an implementation using BigDecimal which gives better results (and is far slower).
import java.math.BigDecimal;
import java.math.RoundingMode;
public class App {
public static double bernoulliNumber2(int n) {
BigDecimal bernoulliN = new BigDecimal(0);
for (long k = 0; k <= n; k++) {
bernoulliN = bernoulliN.add(sum2(k,n));
//System.out.println("B:" + bernoulliN);
}
return bernoulliN.doubleValue();
}
public static BigDecimal sum2(long k, int n) {
BigDecimal result = BigDecimal.ZERO;
for (long v = 0; v <= k; v++) {
BigDecimal vTon = BigDecimal.valueOf(v).pow(n);
result = result.add(BigDecimal.valueOf(Math.pow(-1, v)).multiply(nCr(k,v)).multiply(vTon).divide(BigDecimal.valueOf(k + 1), 1000, RoundingMode.HALF_EVEN));
}
return result;
}
public static BigDecimal nCr(long n, long r) {
return factorial(n).divide(factorial(n - r)).divide(factorial(r));
}
public static BigDecimal factorial(long n) {
if (n == 0) return BigDecimal.ONE;
else return factorial(n-1).multiply(BigDecimal.valueOf(n));
}
public static void main(String[] args) {
for (int i = 0; i < 20; i++) {
System.out.println(i + ": " + bernoulliNumber2(i));
}
}
}
Try changing the scale passed to the division in sum2 and watch the effect on the output.

Write a falling power method

public static long fallingPower(int n, int k)
However, in the related operation of falling power that is useful in many combinatorial formulas and denoted syntactically by underlining the exponent, each term that gets multiplied into the product is always one less than the previous term. For example, the falling power 83 would be computed as 8 * 7 * 6 = 336. Similarly, the falling power 105 would equal 10 * 9 * 8 * 7 * 6 = 30240. Nothing important changes if the base n is negative. For example, the falling power (-4)5 is computed the exact same way as -4 * -5 * -6 * -7 * -8 = -6720.
This method should compute and return the falling power nk where n can be any integer, and k can be any nonnegative integer. (Analogous to ordinary powers, n0 = 1 for any n.) The automated tester is designed so that your method does not need to worry about potential integer overflow as long as you perform computations using long type of 64-bit integers.
public static long fallingPower(int n, int k)
long result = n;
for (int i = n; i < k; i--) {
result = result * n;
}
return result;
}
Is my method right?
It should be:
public static long fallingPower(int n, int k){
long result = n;
for (int i = 0; i < k; i++) {
n=n-1;
result = result * n;
}
return result;
}
You are supposed to multiply k times, starting with n and decrementing each factor by one. Your code currently doesn't really make any sense. I would do it like this:
public static long fallingPower(int n, int k)
long result = n;
for (int i = 1; i < k; i++) {
result = result * (n-i);
}
return result;
}
k is required to be non-negative, so you need to handle that in the method too, for example with an exception:
public static long fallingPower(int n, int k)
if(k < 0) {
throw new IllegalArgumentException("Negative exponent");
}
long result = n;
for (int i = 1; i < k; i++) {
result = result * (n-i);
}
return result;
}
public static long fallingPower(int n, uint k){
long result = 1;
for(; k > 0; k--, n--){
result *= n;
}
return result;
}
This is more of the programming logic, not your method, if I am not wrong. I do not have error handling. I started going backward just like you, assuming the least integer permutation of zero is equal to 1 and at least we need to return 1.
You can start from k number before the n and multiply thereafter until you reach n.
public static long fallingPower(int n, int k)
{
long result = 1;
for (int i = 1 ; i <= k ; i++) {
result = result * n;
n = n-1;
}
return result;
}

Poisson Calc with high factorial

i have this piece of Code for the calc:
public static double CalcPoisson(double m, double u, boolean va)
{
double answer = 0;
if(!va)
{
answer = (Math.exp(-u)* Math.pow(u, m)) / (factorial(m));
}
if(va)
{
for(int i = 0; i < m; i++)
{
answer = answer + (Math.exp(-u)* Math.pow(u, i)) / (factorial(i));
}
}
return answer;
And this was my factorial method
public static double factorial (double n)
{
return n == 0 ? 1 : n *factorial(n-1);
}
Problem is: the maximum value to calculate is 170...i need way more (like factorial of 500)
I have written a new Method:
public static BigDecimal factorial2 (double n)
{
BigDecimal fct = BigDecimal.valueOf(1);
for(int i = 1; i<=n; i++)
{
fct = fct.multiply(BigDecimal.valueOf(i));
}
return fct;
How can i use my new factorialmethod in my "CalcPoisson" Method?
Problem is, i cant divide double with BigDecimal...
Thanks for the help :)
For No One:
I have still this Line of Code in one method that uses CalcPoisson, im still bad with BigDecimal, i cant handle it.
The Line:
BigDecimal nenner = CalcPoisson(m, u, false) + (1-p) * CalcPoisson(m, u, true);
for(int i = 0; i < m; i++)
{
answer = answer + (Math.exp(-u)* Math.pow(u, i)) / (factorial(i));
}
Note that this algorithm computes all factorials from 0 through m-1. Much faster and more accurate to factor that out:
long fact = 1;
for(int i = 0; i < m; i++) {
answer = answer + (Math.exp(-u)* Math.pow(u, i)) / fact;
fact *= (i+1);
}
then note that Math.exp(-u) is invariant in the loop, so extract it:
long fact = 1;
double eu = Math.exp(-u);
for(int i = 0; i < m; i++) {
answer = answer + (eu * Math.pow(u, i)) / fact;
fact *= (i+1);
}
And you can also get rid of the repeated calls to Math.pow():
long fact = 1;
double eu = Math.exp(-u);
double term = u;
for(int i = 0; i < m; i++) {
answer = answer + (eu * term) / fact;
fact *= (i+1);
term *= u;
}
Finally, you can also get combine term and fact into a single parameter (left as an exercise for the student).
You could create a new BigDecimal out of the Double
Then you can use the multiplie method of the BigDecimal
fct = fct.multiplie(new BigDecimal(doubleValue));
Your approach is too direct. Such loops are usually written in terms of while (nextTerm < epsilon) , not as a for loop. That is, of course, provided that you can prove that the terms do decrease with i.
The other problem is that while the value of the expression pow(u,i) / factorial(i) may fit in a double, its parts surely do not. You need to compute this in a different way. Of course, as you do, you lose precision, so it becomes even more complicated.
I should better stop. My Math professor promised that he will hunt down and kill any of us who tried to do computational math, and he was a serious gentleman.
You can convert your double to BigDecimal and then you can divide two BigDecimals as following:
BigDecimal answer = BigDecimal.ZERO;
BigDecimal myOwn = new BigDecimal(Double.toString(Math.exp(-u)* Math.pow(u, i)));
answer = answer.add(myOwn.divide(factorial2(i)));
Use BigDecimal to find Factorial as you have done in factorial2().
Finally your method will look like:
public static BigDecimal CalcPoisson(double m, double u, boolean va)
{
BigDecimal answer = BigDecimal.ZERO;
if(!va)
{
BigDecimal myOwn1 = new BigDecimal(Double.toString((Math.exp(-u)* Math.pow(u, m))));
answer = myOwn1.divide(fakultaet(m));
}
if(va)
{
for(int i = 0; i < m; i++)
{
BigDecimal myOwn = new BigDecimal(Double.toString(Math.exp(-u)* Math.pow(u, i)));
answer = answer.add(myOwn.divide(factorial2(i)));
}
}
return answer;
Assuming that you have return type of method fakultaet() is BigDecimal. And if you have return value double for the same, than try:
answer = myOwn1.divide(new BigDecimal(fakultaet(m)));
EDIT
BigDecimal nenner = CalcPoisson(m, u, false).add((BigDecimal.ONE.subtract(new BigDecimal(p))).multiply( CalcPoisson(m, u, true)));

StackOverFlowError while calculating cos(x) using recursive McLaurin series approximation

I have to write simple code to calculate cos(x) value with McLaurin series approximation. I have to do it recursively. Problem is that with too big angle (param in radians) or too high precision (loop has to stop while last term is smaller or equal than given ε) I get StackOverFlowError. At first I did it non-recursively and it worked perfectly, but it's not fully correct according to assignment. I tried to decrease number of calls for term, but I couldn't fix this. Is there any way to improve this code?
public int factorial(int n) {
int result = 1;
for (int i = 1; i <= n; i++) {
result = result * i;
}
return result;
}
public double term(double x, int n) {
return Math.pow(-1, n) * (Math.pow(x, 2*n) / factorial(2*n));
}
public double laurin(String param, String epsilon) {
double x, eps;
double result = 1;
int n = 0;
x = Double.parseDouble(param);
eps = Double.parseDouble(epsilon);
while(Math.abs(term(x, n)) > eps) {
result += term(x, n) * (term(x, n+1) / term(x, n));
n++;
}
return result;
}
Changing factorial(int n) to non-recursive hasn't changed much, I still get an error real quick.

Calculating powers of integers

Is there any other way in Java to calculate a power of an integer?
I use Math.pow(a, b) now, but it returns a double, and that is usually a lot of work, and looks less clean when you just want to use ints (a power will then also always result in an int).
Is there something as simple as a**b like in Python?
When it's power of 2. Take in mind, that you can use simple and fast shift expression 1 << exponent
example:
22 = 1 << 2 = (int) Math.pow(2, 2)
210 = 1 << 10 = (int) Math.pow(2, 10)
For larger exponents (over 31) use long instead
232 = 1L << 32 = (long) Math.pow(2, 32)
btw. in Kotlin you have shl instead of << so
(java) 1L << 32 = 1L shl 32 (kotlin)
Integers are only 32 bits. This means that its max value is 2^31 -1. As you see, for very small numbers, you quickly have a result which can't be represented by an integer anymore. That's why Math.pow uses double.
If you want arbitrary integer precision, use BigInteger.pow. But it's of course less efficient.
Best the algorithm is based on the recursive power definition of a^b.
long pow (long a, int b)
{
if ( b == 0) return 1;
if ( b == 1) return a;
if (isEven( b )) return pow ( a * a, b/2); //even a=(a^2)^b/2
else return a * pow ( a * a, b/2); //odd a=a*(a^2)^b/2
}
Running time of the operation is O(logb).
Reference:More information
No, there is not something as short as a**b
Here is a simple loop, if you want to avoid doubles:
long result = 1;
for (int i = 1; i <= b; i++) {
result *= a;
}
If you want to use pow and convert the result in to integer, cast the result as follows:
int result = (int)Math.pow(a, b);
Google Guava has math utilities for integers.
IntMath
import java.util.*;
public class Power {
public static void main(String args[])
{
Scanner sc=new Scanner(System.in);
int num = 0;
int pow = 0;
int power = 0;
System.out.print("Enter number: ");
num = sc.nextInt();
System.out.print("Enter power: ");
pow = sc.nextInt();
System.out.print(power(num,pow));
}
public static int power(int a, int b)
{
int power = 1;
for(int c = 0; c < b; c++)
power *= a;
return power;
}
}
Guava's math libraries offer two methods that are useful when calculating exact integer powers:
pow(int b, int k) calculates b to the kth the power, and wraps on overflow
checkedPow(int b, int k) is identical except that it throws ArithmeticException on overflow
Personally checkedPow() meets most of my needs for integer exponentiation and is cleaner and safter than using the double versions and rounding, etc. In almost all the places I want a power function, overflow is an error (or impossible, but I want to be told if the impossible ever becomes possible).
If you want get a long result, you can just use the corresponding LongMath methods and pass int arguments.
Well you can simply use Math.pow(a,b) as you have used earlier and just convert its value by using (int) before it. Below could be used as an example to it.
int x = (int) Math.pow(a,b);
where a and b could be double or int values as you want.
This will simply convert its output to an integer value as you required.
A simple (no checks for overflow or for validity of arguments) implementation for the repeated-squaring algorithm for computing the power:
/** Compute a**p, assume result fits in a 32-bit signed integer */
int pow(int a, int p)
{
int res = 1;
int i1 = 31 - Integer.numberOfLeadingZeros(p); // highest bit index
for (int i = i1; i >= 0; --i) {
res *= res;
if ((p & (1<<i)) > 0)
res *= a;
}
return res;
}
The time complexity is logarithmic to exponent p (i.e. linear to the number of bits required to represent p).
I managed to modify(boundaries, even check, negative nums check) Qx__ answer. Use at your own risk. 0^-1, 0^-2 etc.. returns 0.
private static int pow(int x, int n) {
if (n == 0)
return 1;
if (n == 1)
return x;
if (n < 0) { // always 1^xx = 1 && 2^-1 (=0.5 --> ~ 1 )
if (x == 1 || (x == 2 && n == -1))
return 1;
else
return 0;
}
if ((n & 1) == 0) { //is even
long num = pow(x * x, n / 2);
if (num > Integer.MAX_VALUE) //check bounds
return Integer.MAX_VALUE;
return (int) num;
} else {
long num = x * pow(x * x, n / 2);
if (num > Integer.MAX_VALUE) //check bounds
return Integer.MAX_VALUE;
return (int) num;
}
}
base is the number that you want to power up, n is the power, we return 1 if n is 0, and we return the base if the n is 1, if the conditions are not met, we use the formula base*(powerN(base,n-1)) eg: 2 raised to to using this formula is : 2(base)*2(powerN(base,n-1)).
public int power(int base, int n){
return n == 0 ? 1 : (n == 1 ? base : base*(power(base,n-1)));
}
There some issues with pow method:
We can replace (y & 1) == 0; with y % 2 == 0
bitwise operations always are faster.
Your code always decrements y and performs extra multiplication, including the cases when y is even. It's better to put this part into else clause.
public static long pow(long x, int y) {
long result = 1;
while (y > 0) {
if ((y & 1) == 0) {
x *= x;
y >>>= 1;
} else {
result *= x;
y--;
}
}
return result;
}
Use the below logic to calculate the n power of a.
Normally if we want to calculate n power of a. We will multiply 'a' by n number of times.Time complexity of this approach will be O(n)
Split the power n by 2, calculate Exponentattion = multiply 'a' till n/2 only. Double the value. Now the Time Complexity is reduced to O(n/2).
public int calculatePower1(int a, int b) {
if (b == 0) {
return 1;
}
int val = (b % 2 == 0) ? (b / 2) : (b - 1) / 2;
int temp = 1;
for (int i = 1; i <= val; i++) {
temp *= a;
}
if (b % 2 == 0) {
return temp * temp;
} else {
return a * temp * temp;
}
}
Apache has ArithmeticUtils.pow(int k, int e).
import java.util.Scanner;
class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
for (int i = 0; i < t; i++) {
try {
long x = sc.nextLong();
System.out.println(x + " can be fitted in:");
if (x >= -128 && x <= 127) {
System.out.println("* byte");
}
if (x >= -32768 && x <= 32767) {
//Complete the code
System.out.println("* short");
System.out.println("* int");
System.out.println("* long");
} else if (x >= -Math.pow(2, 31) && x <= Math.pow(2, 31) - 1) {
System.out.println("* int");
System.out.println("* long");
} else {
System.out.println("* long");
}
} catch (Exception e) {
System.out.println(sc.next() + " can't be fitted anywhere.");
}
}
}
}
int arguments are acceptable when there is a double paramter. So Math.pow(a,b) will work for int arguments. It returns double you just need to cast to int.
int i = (int) Math.pow(3,10);
Without using pow function and +ve and -ve pow values.
public class PowFunction {
public static void main(String[] args) {
int x = 5;
int y = -3;
System.out.println( x + " raised to the power of " + y + " is " + Math.pow(x,y));
float temp =1;
if(y>0){
for(;y>0;y--){
temp = temp*x;
}
} else {
for(;y<0;y++){
temp = temp*x;
}
temp = 1/temp;
}
System.out.println("power value without using pow method. :: "+temp);
}
}
Unlike Python (where powers can be calculated by a**b) , JAVA has no such shortcut way of accomplishing the result of the power of two numbers.
Java has function named pow in the Math class, which returns a Double value
double pow(double base, double exponent)
But you can also calculate powers of integer using the same function. In the following program I did the same and finally I am converting the result into an integer (typecasting). Follow the example:
import java.util.*;
import java.lang.*; // CONTAINS THE Math library
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n= sc.nextInt(); // Accept integer n
int m = sc.nextInt(); // Accept integer m
int ans = (int) Math.pow(n,m); // Calculates n ^ m
System.out.println(ans); // prints answers
}
}
Alternatively,
The java.math.BigInteger.pow(int exponent) returns a BigInteger whose value is (this^exponent). The exponent is an integer rather than a BigInteger. Example:
import java.math.*;
public class BigIntegerDemo {
public static void main(String[] args) {
BigInteger bi1, bi2; // create 2 BigInteger objects
int exponent = 2; // create and assign value to exponent
// assign value to bi1
bi1 = new BigInteger("6");
// perform pow operation on bi1 using exponent
bi2 = bi1.pow(exponent);
String str = "Result is " + bi1 + "^" +exponent+ " = " +bi2;
// print bi2 value
System.out.println( str );
}
}

Categories