Java pow implementation with Integer.MIN_VALUE as exponent - java

I am implementing a pow function in Java, and I am wondering how do we deal with Integer.MIN_VALUE as a exponent ? Do we just treat it as a special case ?
Because I tried to compare the result with the standard Java.lang.Math API and I get a couple different result. The following is the list of comparison
//this will print "1.0 vs 0.0"
System.out.println(pow(2,Integer.MIN_VALUE) + " vs " + Math.pow(2,Integer.MIN_VALUE));
//this will print "1.0 vs 1.0"
System.out.println(pow(1,Integer.MIN_VALUE) + " vs " + Math.pow(1,Integer.MIN_VALUE));
public double pow(double base, int exp){
double result = 1.0;
boolean pos = false;
if(exp == 0) return result;
if(exp > 0){
pos = true;
exp *= -1;
}
while(exp > 0){
if((exp & 1) == 1){
result *= base;
}
base *= base;
exp /= 2;
}
if(!pos){
result = 1/result;
}
return result;
}
So I am wondering if Integer.MIN_VALUE is a special case where I have to have a if statement for checking it.
if(exp == Integer.MIN_VALUE && base > 1) return 0.0;

Based on this line:
exp *= -1;
it seems that it might have to be a special case. There are certainly ways to implement this without that special case, but because -1 * Integer.MIN_VALUE cannot be stored in an int, you will get a bug if you do not handle it separately.

Yeah, you've got the problem that Integer.MIN_VALUE * -1 == Integer.MIN_VALUE. You could either special-case it, or you could deal with it another way. Indeed, one possible solution would be to make exp negative when it's positive, instead of the other way around; you'd just use -exp instead of exp.

On my system I have
-2147483648
2147483647
For Integer.MIN_VALUE and Integer.MAX_VALUE respectively. So you should see the problem in the line
exp *= -1;

Well, the real issue is that, since the sign doesn't flip on the MIN_VALUE, the sign cascades to the exp/2. and the 'negative power' case applies. If we split it, it's easier:
public double myPow(double x, int n) {
double result = 1.00000;
boolean negative = false;
if(n <0) {
negative = true;
n= -n;
}
result=power(x,n);
if(negative) {
result = 1/result;
}
return result;
}
private double power(double a, int n) {
if(n ==0 || a==1) return 1;// a^0 = 1, 1^n = 1
double x=power(a,n/2);
if(n%2 == 0) return x*x;
else return a*x*x;
}

Related

Reverse Integer (Leetcode)

I was trying to solve 7.Reverse Integer on leetcode https://leetcode.com/problems/reverse-integer/.
Given a signed 32-bit integer x, return x with its digits reversed. If reversing x causes the value to go outside the signed 32-bit integer range [-2^31, 2^31 - 1], then return 0.
Example 1:
Input: x = 123
Output: 321
My solution for the above problem is
class Solution {
public int reverse(int x) {
int num=0;
if(x>Integer.MAX_VALUE||x<Integer.MIN_VALUE) return 0;
while(x!=0){
int a=x%10;
num=num*10+a;
x=x/10;
}
return num;
}
}
I'm getting 4 test cases wrong. One of which is :
Example
Input: 1534236469
Output : 1056389759
Expected: 0
Your problem is that the overflow is in the num variable and you are not checking for that. By adding a check to make sure the calculation will not overflow before performing num = num*10+a, you can return 0 when necessary.
Also, you weren't handling negative numbers properly. A check for a negative up front can allow you to work with a positive number and then just negate the result.
class Solution {
public int reverse(int x) {
int num=0;
Boolean negative = false;
if (x < 0) {
x = -x;
negative = true;
}
while(x!=0){
int a=x%10;
// Check if the next operation is going to cause an overflow
// and return 0 if it does
if (num > (Integer.MAX_VALUE-a)/10) return 0;
num=num*10+a;
x=x/10;
}
return negative ? -num : num;
}
}
The approach you've chosen is not that far off.
You currently check the input x to be in range of unsigned integer. But they ask to check x-reversed instead.
You aggregate your answer in an integer, hence you might overflow unnoticed.
Both of your problems can be solved if you aggregate your result num in an variable of type long instead and reject/zero the answer if after reversing it is out of bounds of unsigned int.
Alternative you can use Math.addExact(a, b), Math.multiplyExact(a,b) and a try-catch to exit immediately upon overflow.
Input: 123
Output: 321
Input: -123
Output: -321
Input: 120
Output: 2
class Solution {
public:
int reverse(int x) {
int rev = 0;
constexpr int top_limit = INT_MAX/10;
constexpr int bottom_limit = INT_MIN/10;
while (x) {
if (rev > top_limit || rev < bottom_limit)
return 0;
rev = rev * 10 + x % 10;
x /= 10;
}
return rev;
}
};
You're not dealing with the theoretical signed 32-bit integer overflow that might occur in the loop, meaning you'll sometimes return a number outside of that range. Also, the logic will not work as expected with negative values.
And to be really precise on the restriction of signed 32-bit, special care needs to be taken when the input is -231, as its absolute value does not represent a valid signed 32-bit integer.
class Solution {
public int reverse(int x) {
if (x < 0) return x == -2147483648 ? 0 : -reverse(-x);
int res = 0;
while (x > 0 && res < 214748364) {
res = res * 10 + x % 10;
x /= 10;
}
return x == 0 ? res
: res > 214748364 || x > 7 ? 0
: res * 10 + x;
}
}

How to detect overflow on power in Java

I know that java.lang.Math provides a set of static methods to perform some operations (sum, difference, multiply, increment, decrement, negate, toInt), throwing an ArithmeticException on overflow.
Is there something similar for power?
No, there is nothing equivalent for pow built into Java. (The only pow methods built into Java are Math.pow, which accepts doubles and does not overflow in the same way integers do, and BigInteger.pow, which does not overflow because BigIntegers can be arbitrarily large.)
If third-party libraries are acceptable, though, Guava has e.g. IntMath.checkedPow, which does what you're looking for.
As Chirag said, integers throw exceptions when they overflow while doubles don't. Not to get too specific but, basically, doubles in memory are stored very similarly to scientific notation, in that they are some integer * 2^(some power), and thus never really overflow but multiply by such a large or small 2^(some power) that they completely lose their precision. So you can instead think of double overflow as when they completely lose their precision and are printed as either Infinity or -Infinity.
So, you will need to manually check that an overflow has occurred by checking if the resulting value is Double.POSITIVE_INFINITY or Double.NEGATIVE_INFINITY.
Here is some sample code to show what I mean:
public static void main(String[] args) throws Exception
{
double a = Double.MAX_VALUE; // highest possible double
double b = Double.MAX_VALUE; // highest possible double
if (Math.pow(a, b) == Double.POSITIVE_INFINITY || Math.pow(a, b) == Double.NEGATIVE_INFINITY)
{
throw new ArithmeticException("Double Overflow");
}
}
If it's fine to have your own implementation, you could do something like this:
private static final int[] maxBaseForExponent = IntStream.range(0, 30)
.map(e -> (int) Math.pow(Integer.MAX_VALUE, 1d / e)).toArray();
public static int powExact(int base, int exponent) {
if (exponent < 0) {
throw new ArithmeticException("Negative exponent");
}
if ((base < -1 || base > 1) && (exponent > 30 || base > maxBaseForExponent[exponent])
&& !(base == -2 && exponent == 31)) {
throw new ArithmeticException("Overflow");
}
switch (base) {
case -2:
return (exponent & 1) == 0 ? 1 << exponent : -1 << exponent;
case -1:
return (exponent & 1) == 0 ? 1 : -1;
case 0:
return exponent == 0 ? 1 : 0;
case 1:
return 1;
case 2:
return 1 << exponent;
default:
}
int result = 1;
while (exponent != 0) {
if ((exponent & 1) != 0) {
result *= base;
}
exponent >>= 1;
base *= base;
}
return result;
}
Took the algorithm from here, and modified it to check for overflow using an array which contains max base for each exponent from 0 to 30.
Integers are only 32 bits. so max value is 2^31 -1. ( If using BigInteger.pow. It is less efficient.)
So you can check manually and throw Exception if required
else use Math.pow which uses double.

Recursive method for x^n optimised for when n is even

I need to write a recursive method using Java called power that takes a double x and an integer n and that returns x^n. Here is what I have so far.
public static double power(double x, int n) {
if (n == 0)
return 1;
if (n == 1)
return x;
else
return x * (power(x, n-1));
}
This code works as expected. However, I am trying to go the extra mile and perform the following optional exercise:
"Optional challenge: you can make this method more efficient, when n is even, using x^n = (x^(n/2))^2."
I am not sure how to implement that last formula when n is even. I do not think I can use recursion for that. I have tried to implement the following, but it also does not work because I cannot take a double to the power of an int.
if (n%2 == 0)
return (x^(n/2))^2;
Can somebody point me in the right direction? I feel like I am missing something obvious. All help appreciated.
It's exactly the same principle as for x^n == x*(x^(n-1)): Insert your recursive function for x^(n/2) and (...)^2, but make sure you don't enter an infinite recursion for n == 2 (as 2 is even, too):
if (n % 2 == 0 && n > 2)
return power(power(x, n / 2), 2);
}
Alternatively, you could just use an intermediate variable:
if (n % 2 == 0) {
double s = power(x, n / 2);
return s * s;
}
I'd probably just handle 2 as a special case, too -- and avoid the "and"-condition and extra variable:
public static double power(double x, int n) {
if (n == 0) return 1;
if (n == 1) return x;
if (n == 2) return x * x;
if (n % 2 == 0) return power(power(x, n / 2), 2);
return x * (power(x, n - 1));
}
P.S. I think this should work, too :)
public static double power(double x, int n) {
if (n == 0) return 1;
if (n == 1) return x;
if (n == 2) return x * x;
return power(x, n % 2) * power(power(x, n / 2), 2);
}
When n is even, the formula is exactly what you wrote: divide n by two, call power recursively, and square the result.
When n is odd, the formula is a little more complex: subtract 1 from n, make a recursive call for n/2, square the result, and multiply by x.
if (n%2 == 0)
return (x^(n/2))^2;
else
return x*(x^(n/2))^2;
n/2 truncates the result, so subtraction of 1 is not done explicitly. Here is an implementation in Java:
public static double power(double x, int n) {
if (n == 0) return 1;
if (n == 1) return x;
double pHalf = power(x, n/2);
if (n%2 == 0) {
return pHalf*pHalf;
} else {
return x*pHalf*pHalf;
}
}
Demo.
Hint: The ^ operation won't perform exponentiation in Java, but the function you wrote, power will.
Also, don't forget squaring a number is the same as just multiplying it by itself. No function call needed.
Making a small change to your function, it will reduce the number of recursive calls made:
public static double power(double x, int n) {
if (n == 0) {
return 1;
}
if (n == 1) {
return x;
}
if (n % 2 == 0) {
double temp = power(x, n / 2);
return temp * temp;
} else {
return x * (power(x, n - 1));
}
}
Since
x^(2n) = (x^n)^2
you can add this rule to your method, either using the power function you wrote, as Stefan Haustein suggested, or using the regular multiplication operator, since it seems you are allowed to do that.
Note that there is no need for both the base cases n=1 and n=0, one of them suffices (prefferably use the base case n=0, since otherwise your method would not be defined for n=0).
public static double power(double x, int n) {
if (n == 0)
return 1;
else if (n % 2 == 0)
double val = power(x, n/2);
return val * val;
else
return x * (power(x, n-1));
}
There is no need to check that n>2 in any of the cases.
This just reminds me more optimisation could be done
and this following code.
class Solution:
# #param x, a float
# #param n, a integer
# #return a float
def pow(self, x, n):
if n<0:
return 1.0/self.pow(x,-n)
elif n==0:
return 1.0
elif n==1:
return x
else:
m = n & (-n)
if( m==n ):
r1 = self.pow(x,n>>1)
return r1*r1
else:
return self.pow(x,m)*self.pow(x,n-m)
what is more intermediate result could be memorised and avoid redundant computation.

Why does the logarithm algorithm for Divide Two Integers fail some special test cases?

I tried to used the formula a/b = e^(ln a - ln b) to solve the infamous Divide 2 Integers without using / % * question, however for some test cases (dividend=Integer.MAX_VALUE or MIN_VALUE and divisor=1) my solution fails.
Why does it fail?
[EDIT]: The answers I get for that test case are (MAX-1 or MIN+1). I'd like to know why this happens.
public int divide(int dividend, int divisor) {
boolean neg = false;
if ((dividend < 0 && divisor > 0) || (dividend > 0 && divisor < 0))
neg = true;
long a = dividend;
a = Math.abs(a);
long b = divisor;
b = Math.abs(b);
double res = Math.pow(Math.E, Math.log(a) - Math.log(b));
int ans = Math.floor(res);
return neg ? -ans : ans;
}
The root of the problem here is in intermediate results of calculations.
Double is a floating-point type, when you use it, you may loose precision.
You use double in your intermediate calculations:
double res = Math.pow(Math.E, Math.log(a) - Math.log(b));
int ans = Math.floor(res);
For example if you use 5 and 1, res = 4.999999999999, Math.floor(res) will return 4.
With Integer.MAX_VALUE you have 2147483647 (original value), but the result is 2147483646. The reason is exactly the same as for 5.

What's wrong with this code to make it not add the divisors to sum each time?

I've beeen trying to get a program written for a lab for class, and I believe I almost have it, but it won't add up the divisors (div in the code) to the sum and return true if it is a perfect number and false otherwise. My code compiles and runs fine but will only return a false, presumably because sum is staying at 1 (it initializes at one since 1 is a divisor of every number). number is a private int brought in from the constructors and set statements.
public boolean isPerfect()
{
int x = number -1 ;
int div = 0;
int sum = 1;
while(x> 1)
{
if(number % x == 0)
{
div = x;
sum=+ div;
}
x--;
}
if(sum == number)
{
return true;
}
else
{
return false;
}
}
This is backwards. sum =+ div; should be sum += div;
What you have is basically sum = (+div), in other words positive div.
As well as the += / =+ issue, your code also says that 1 is a perfect number, which is incorrect (6 is the first perfect number). This is because you start with a sum of 1, the loop won't execute at all, then you compare sum and number, which are equal for 1. You could just add a check for this special case, e.g.
if(sum == number && number > 1)...
Additional tip - instead of :
if(sum == number)
{
return true;
}
else
{
return false;
}
You can just use:
return (sum == number);
You could have sum= sum + div; or sum += div;
also where is your number variable define i guess it is something like public boolean isPerfect(int number)

Categories

Resources