I am only interested in n < 0 case, if n == -3 then I get, 0.001 as desired.
but I reached here through trial and error. Can someone explain to me 'WHY' this works (for n < 0 case only)?
public static double power10(int n) {
if(n == 0){
return 1;
}
else if (n > 10){
return 10 * power10(n - 1);
}
else {
return 1.0 / power10(-n);
}
}
The Following Function works for both negative and positive powers.
double Power(int n1,int n2) {
if(n2>=0) {
if(n2==1) {
return n1;
}
if(n2==0) {
return 1;
}
else {
return n1*Power(n1,n2-1);
}
}
else {
if(n2==-1) {
return 1.0/n1;
}
else {
return 1.0/(n1*Power(n1,(-1)*(n2+1)));
}
}
It will create following recursion tree for Negative example,
This link will redirect you to the recursion tree to better understanding, How this function will work recursively.
In fact, your code doesn't work for either 3 or -3. A stack overflow occurs in both cases. I don't know how you got 0.003.
The error in your code is this:
else if (n > 10){
It should be n > 0. instead.
This recursive algorithm should be quite clear if we turn it into a sentence starting with "the nth power of 10 is...":
The nth power of 10 is:
If n is 0, 1
If n is positive, 10 * (n-1)th power of 10
If n is negative, 1 / -nth power of 10
You can see that all values of n are covered, whether it be 0, positive or negative. In your incorrect code, you treat cases where 0 < n < 10 as "negative numbers". When you negate those and recurse, you get a real negative number, it goes into the else again and they are negated again. But they are still not larger than 10, causing infinite recursion.
Your code here probably give out stack overflow error.
Try
else if(n>0)
Now under the above condition function return n th value of 10 and return 1000 (when n is 3 case), Giving you the answer 0.001.
Related
I am trying to write a Java method that checks whether a number is a perfect number or not.
A perfect number is a number that is equal to the sum of all its divisor (excluding itself).
For example, 6 is a perfect number because 1+2+3=6. Then, I have to write a Java program to use the method to display the first 5 perfect numbers.
I have no problem with this EXCEPT that it is taking forever to get the 5th perfect number which is 33550336.
I am aware that this is because of the for loop in my isPerfectNumber() method. However, I am very new to coding and I do not know how to come up with a better code.
public class Labreport2q1 {
public static void main(String[] args) {
//Display the 5 first perfect numbers
int counter = 0,
i = 0;
while (counter != 5) {
i++;
isPerfectNumber(i);
if (isPerfectNumber(i)) {
counter++;
System.out.println(i + " ");
}
}
}
public static boolean isPerfectNumber(int a) {
int divisor = 0;
int sum = 0;
for (int i = 1; i < a; i++) {
if (a % i == 0) {
divisor = i;
sum += divisor;
}
}
return sum == a;
}
}
This is the output that is missing the 5th perfect number
Let's check the properties of a perfect number. This Math Overflow question tells us two very interesting things:
A perfect number is never a perfect square.
A perfect number is of the form (2k-1)×(2k-1).
The 2nd point is very interesting because it reduces our search field to barely nothing. An int in Java is 32 bits. And here we see a direct correlation between powers and bit positions. Thanks to this, instead of making millions and millions of calls to isPerfectNumber, we will be making less than 32 to find the 5th perfect number.
So we can already change the search field, that's your main loop.
int count = 0;
for (int k = 1; count < 5; k++) {
// Compute candidates based on the formula.
int candidate = (1L << (k - 1)) * ((1L << k) - 1);
// Only test candidates, not all the numbers.
if (isPerfectNumber(candidate)) {
count++;
System.out.println(candidate);
}
}
This here is our big win. No other optimization will beat this: why test for 33 million numbers, when you can test less than 100?
But even though we have a tremendous improvement, your application as a whole can still be improved, namely your method isPerfectNumber(int).
Currently, you are still testing way too many numbers. A perfect number is the sum of all proper divisors. So if d divides n, n/d also divides n. And you can add both divisors at once. But the beauty is that you can stop at sqrt(n), because sqrt(n)*sqrt(n) = n, mathematically speaking. So instead of testing n divisors, you will only test sqrt(n) divisors.
Also, this means that you have to start thinking about corner cases. The corner cases are 1 and sqrt(n):
1 is a corner case because you if you divide n by 1, you get n but you don't add n to check if n is a perfect number. You only add 1. So we'll probably start our sum with 1 just to avoid too many ifs.
sqrt(n) is a corner case because we'd have to check whether sqrt(n) is an integer or not and it's tedious. BUT the Math Overflow question I referenced says that no perfect number is a perfect square, so that eases our loop condition.
Then, if at some point sum becomes greater than n, we can stop. The sum of proper divisors being greater than n indicates that n is abundant, and therefore not perfect. It's a small improvement, but a lot of candidates are actually abundant. So you'll probably save a few cycles if you keep it.
Finally, we have to take care of a slight issue: the number 1 as candidate. 1 is the first candidate, and will pass all our tests, so we have to make a special case for it. We'll add that test at the start of the method.
We can now write the method as follow:
static boolean isPerfectNumber(int n) {
// 1 would pass the rest because it has everything of a perfect number
// except that its only divisor is itself, and we need at least 2 divisors.
if (n < 2) return false;
// divisor 1 is such a corner case that it's very easy to handle:
// just start the sum with it already.
int sum = 1;
// We can stop the divisors at sqrt(n), but this is floored.
int sqrt = (int)Math.sqrt(n);
// A perfect number is never a square.
// It's useful to make this test here if we take the function
// without the context of the sparse candidates, because we
// might get some weird results if this method is simply
// copy-pasted and tested on all numbers.
// This condition can be removed in the final program because we
// know that no numbers of the form indicated above is a square.
if (sqrt * sqrt == n) {
return false;
}
// Since sqrt is floored, some values can still be interesting.
// For instance if you take n = 6, floor(sqrt(n)) = 2, and
// 2 is a proper divisor of 6, so we must keep it, we do it by
// using the <= operator.
// Also, sqrt * sqrt != n, so we can safely loop to sqrt
for (int div = 2; div <= sqrt; div++) {
if (n % div == 0) {
// Add both the divisor and n / divisor.
sum += div + n / div;
// Early fail if the number is abundant.
if (sum > n) return false;
}
}
return n == sum;
}
These are such optimizations that you can even find the 7th perfect number under a second, on the condition that you adapt the code for longs instead of ints. And you could still find the 8th within 30 seconds.
So here's that program (test it online). I removed the comments as the explanations are here above.
public class Main {
public static void main(String[] args) {
int count = 0;
for (int k = 1; count < 8; k++) {
long candidate = (1L << (k - 1)) * ((1L << k) - 1);
if (isPerfectNumber(candidate)) {
count++;
System.out.println(candidate);
}
}
}
static boolean isPerfectNumber(long n) {
if (n < 2) return false;
long sum = 1;
long sqrt = (long)Math.sqrt(n);
for (long div = 2; div <= sqrt; div++) {
if (n % div == 0) {
sum += div + n / div;
if (sum > n) return false;
}
}
return n == sum;
}
}
The result of the above program is the list of the first 8 perfect numbers:
6
28
496
8128
33550336
8589869056
137438691328
2305843008139952128
You can find further optimization, notably in the search if you check whether 2k-1 is prime or not as Eran says in their answer, but given that we have less than 100 candidates for longs, I don't find it useful to potentially gain a few milliseconds because computing primes can also be expensive in this program. If you want to check for bigger perfect primes, it makes sense, but here? No: it adds complexity and I tried to keep these optimization rather simple and straight to the point.
There are some heuristics to break early from the loops, but finding the 5th perfect number still took me several minutes (I tried similar heuristics to those suggested in the other answers).
However, you can rely on Euler's proof that all even perfect numbers (and it is still unknown if there are any odd perfect numbers) are of the form:
2i-1(2i-1)
where both i and 2i-1 must be prime.
Therefore, you can write the following loop to find the first 5 perfect numbers very quickly:
int counter = 0,
i = 0;
while (counter != 5) {
i++;
if (isPrime (i)) {
if (isPrime ((int) (Math.pow (2, i) - 1))) {
System.out.println ((int) (Math.pow (2, i -1) * (Math.pow (2, i) - 1)));
counter++;
}
}
}
Output:
6
28
496
8128
33550336
You can read more about it here.
If you switch from int to long, you can use this loop to find the first 7 perfect numbers very quickly:
6
28
496
8128
33550336
8589869056
137438691328
The isPrime method I'm using is:
public static boolean isPrime (int a)
{
if (a == 1)
return false;
else if (a < 3)
return true;
else {
for (int i = 2; i * i <= a; i++) {
if (a % i == 0)
return false;
}
}
return true;
}
I've got this code
public class FiboNegativV {
int negativ(int nv) {
if (nv ==0)
return 1;
if (nv ==1)
return 2;
return negativ(nv-1) + negativ(nv-2);
}
}
Now I would like to turn the final number into negative. I've tried a few things like "nv = -nv;" But I usually got stackover when I put it before the
"return negativ(nv-1) + negativ(nv-2)" and it is unreachable when it's after this line.
You don't need function for that just do it like this:
int x *= -1;
All the other answers for some reason disregard your initial intention of a Fibbonacci sequence. But I do not understand why they do not keep the context. Your method obviously tries to do a Fibbonacci sequence with recursion yielding negative numbers.
Now I would like to turn the final number into negative.
The simplest and most intuitive way of negatinv a number is to use a unary minus operator = just add a minus before the expression (so negating x to -x). We use this only on positive numbers, so that the negative ones stay negative: (note: this is a ternary operator)
(result > 0) ? -result : result;
However the big mistake is that you do NOT handle negative numbers in the recursive method in the first place! Of course you run into stack overflow, because the recursive negative numbers are going to get lower and lower.
static int negativFib(int nv)
{
//turn negative input into positive
nv = nv < 0 ? -nv : nv;
//base cases
if (nv == 0)
return 1;
if (nv == 1)
return 2;
final int result = negativFib(nv - 1) + negativFib(nv - 2);
//turn the number into negative
return result > 0 ? -result : result;
}
Alternative algorithm
An another problem which could occur is that with big numbers, the recursion comes to a stack overflow. You could prevent this by using some other algorithm, f.e. dynamic programming. With dynamic programming Fibbonacci sequence you store the previous 2 results every time and solve the problem in iterations, instead of recursion.
If you only want to convert positive into negative then
nv = (nv > 0) ? nv * -1 : nv
if you want to convert positive to negative and negative to positive then
nv = nv * -1
Below your code will look like
public class FiboNegativ
{
public FiboNegativV(){}
int negativ(int nv)
{
return (nv > 0) ? nv*-1 : nv;
}
}
Since you want only the final number to be negative, the easiest way is to work with absolute numbers, and return negative numbers, as per the following:
public class FiboNegativV {
int negativ(int nv) {
return (nv == 0) ? -1 :
(nv == 1) ? -2 :
-(Math.abs(negativ(nv-1)) + Math.abs(negativ(nv-2)));
}
}
The assumption I have made, above, is that the initial input to the function will always be positive. Your original code confirms this assumption.
-1 * (Math.abs(negativ(nv-1) + negativ(nv-2)));
Thus the result will be negative regardless of the values given.
I need help with a program that satisfies the following quote:
All integers >= 2 can be factored into the product of only prime
numbers. For instance, the number 12 has a prime factorization of
2*2*3, while the number 100 has a prime factorization of 2*2*5*5. We
are interested in knowing whether an input integer has a prime
factorization that only has 2s and 3s.
I think I need more base conditions and a catch all recursive call.
Current (unfinished) Code:
public static boolean hasFactors2and3(int number) throws IllegalArgumentException{
if (number < 2) throw new IllegalArgumentException("Number is less than 2");
if (number >= 2 && number < 5) return true; // because for all these numbers it works
if (number % 2 == 0) return hasFactors2and3(number /= 2);
if (number % 3 == 0) return hasFactors2and3(number /= 3);
}
Any help is appreciated!
You ask for a recursive solution. I won't give you that. Instead I will give you a non-recursive solution in pseudocode and leave it up to you to convert it into a recursive solution.
function hasFactors2and3(number)
// Deal with negatives, 0, 1.
if (number < 2)
return false
endif
// Remove factors of 2.
while (number MOD 2 == 0)
number <- number / 2
endwhile
// Remove factors of 3.
while (number MOD 3 == 0)
number <- number / 3
endwhile
// See what factors are left after removing all 2s and 3s.
return number == 1
end function
Hint: research how to remove tail recursion by using a loop and then reverse the process.
Could anyone explain how does this method works.
public static int calculate(int n){
if (n/10 == 0)
return n;
else
return (n % 10 + calculate(n/10));
}
I input n = 15 and it get a 6 but I don't understand how the method works. please help. thank you.
The method calculates the sum of the digits.
If the n is smaller than 10, you simply return n (since the sum of digits of a single digit number is the number itself).
Otherwise you add the least significant digit (that's n % 10) to the sum of digits of the number n / 10 (which is calculated recursively).
For n = 15 , here is how it works
15/10 > 0 , so the else condition is executed.
15%10 + calculate(15/10) i.e 5 + calculate(1).
The method is called again for n = 1;
Since 1/10 == 0 , 1 is returned
This 1 is then added to 5.
Therefore answer is 6.
So what this function does is return the sum of the digits that make up the number.
It goes like this:
calculate(15);
evaluates to
15%10 + calculate(1);
evaluates to
5 + 1;
which in the end; sums up to 6.
In other words; the above is an recursive approach to sum all the digits in a number. You could easily re-write this using a simple loop to avoid the recursion construct.
It cuts off the most right digit and moves on recursively with the rest of the number. (line 5)
If we have only one digit left (line 2), it is also added to the sum and the algorithm ends. (line 3)
In this example there is a if else condition so on the basis of input parameter there are 2 conditions '
-Firstly it checks in the if condition (n/10 == 0) .
-Consider your input as n=15.
now it checks if (n/10 == 0) i.e 15/10==0 which is false because 15/10=5 which is not equal to 0.
-As the condition is false it moves to else block where condition is to return
(n % 10 + calculate(n/10)
i.e. (15%10 +15/10)==5+1==6
-So the return is 6.
Problem: check if a number is a power of 4.
my solution in java:
public static boolean isPowerOfFour(int num) {
return (Math.log(num) % Math.log(4) == 0);
}
But it seems off in some cases, for example when num is 64.
I found out that if I change the code a little bit, it works well.
public static boolean isPowerOfFour(int num) {
return (Math.log(num) / Math.log(4) %1 == 0);
}
I think both solutions do the same thing, check if the remaining of logNum/logBase is 0. But why the first solution doesn't work? Is it because the solution is incorrect or relative to some low level JVM stuff?
Thanks.
Building on #dasblinkenlight's answer, you can easily combine both conditions (first, a power of 2, then any power of 4 among all possible powers of 2) with a simple mask:
public static boolean isPowerOfFour(int num) {
return ((( num & ( num - 1 )) == 0 ) // check whether num is a power of 2
&& (( num & 0xaaaaaaaa ) == 0 )); // make sure it's an even power of 2
}
No loop, no conversion to float.
Checking if a number is a power of 4 is the same as checking that the number is an even power of 2.
You can check that a number x is a power of two by verifying that x & (x-1) is zero (here is the explanation of how this works)
If your number is not a power of 2, return false. Otherwise, shift the number right until you get to one, and count the number of shifts. If you shifted an odd number of times, return false; otherwise, return true:
public static boolean isPowerOfFour(int num) {
if ((num & (num-1)) != 0) {
return false;
}
int count = 0;
while (num != 1) {
num >>= 1;
count++;
}
return count % 2 == 0;
}
Demo.
Functions like Math.log return floating point numbers with a rounding error. So when num = 64 for example, Math.log (num) / Math.log (4) is not exactly 3, but a number close to 3.
public static boolean isPowerOfFour(int num) {
if (num > 0) {
while (num % 4 == 0) num /= 4;
}
return (num == 1);
}
This solution can be quite easily adapted to check whether num is a power of some other integer greater than 1.
The reason it doesn't work is because Math.log() returns a double. The answer of false is reflective of rounding errors; log(64) base e is an irrational number but Java needs to truncate it to fit it's width.