public int sumOfDigits(int num){
return num == 0 ? 0 : num % 10 + sumOfDigits(num/10);
}
This is a recursive calculation of the sum of digits - as long as you haven't consumed all the digits, it adds the last one with the sum of all the previous ones.
sumOfDigits is a method which accepts int argument and the return type is also int.
If 0 is passed then it will return 0 other wise it will return num % 10 + sumOfDigits(num/10)
If a number other than 0 is passed this will continue as long as entered number becomes 0
return num == 0 ? 0 : num % 10 + sumOfDigits(num/10);
Is equivalent to:
if(num==0)
{
return 0;
}
else
{
return num % 10 + sumOfDigits(num/10); // this is recursive call. It gets called until num is reduce to 0
}
This basically calulates as following:
If num=768 result= 7+6+8.
That is the Java ternary operator. It is similar to ternary operators in other languages. In this case:
return <boolean expression> ? <if true> : <if false>;
You have posted a recursive algorithm to calculate the sum of digits in an integer.
Two equivalent methods are posted below:
public int sumOfDigitsIf(int num) {
if (num == 0) {
return 0;
} else {
return num % 10 + sumOfDigitsIf(num / 10);
}
}
public int sumOfDigitsLoop(int num) { // useful to examine if you aren't used to recursive algorithms
int value = 0;
while (num > 0) {
value += num % 10;
num /= 10;
}
return value;
}
This function calculates the sum of the digits of the number recursively. First, if the number is 0, it returns 0, as the sum of the digits of 0 is 0. Then, it calculates the digit in the 1s place with num % 10, and adds that to the sum of the digits of the remaining places, num / 10 is the remaining places, and it calls sumOfDigits() on that number.
This method calculates sum of the numbers representing base 10 integer numbers. The method is called recursively with % operator to separate digits in the number and then add them to form the result.
Eg - 234 into 2 + 3 + 4 = 9
However, if you pass a integer in base other than base 10, the method still gives the result for base 10
Eg sumOfDigits(0b1011010) -> answer is 9 for 90 in base 10
sumOfDigits(0x532) -> answer is 7 for 1330 in base 10
Following is the change for binary and octal values to get the sum of the representing numbers
return num == 0 ? 0 : num % 2 + sumOfDigits(num / 2);
return num == 0 ? 0 : num % 8 + sumOfDigits(num / 8);
That's a Java ternary operator, but in most cases it is not used since if-else statements are much more readable, which can also do the same function ternary operators can do. But if you would like to make shorter code lines, then this is preferred.
Related
I have a question regarding an answer that was given here a while ago.
I came up with the same answer myself in the code attached but I'm trying to understand why do I need to divide the input number by 2 (line 10), and not just let the loop run its course till the value of the input number achieved.
1 import java.util.Scanner;
2 public class numIsPrime {
3 public static void main(String[] args) {
4 Scanner sc = new Scanner(System.in);
5 int i = 2;
6 boolean isPrime = true;
7 System.out.println("Enter a number");
8 int num = sc.nextInt();
9
10 while (i < num ) // (i <= num / 2)
11 {
12 if (num % i == 0)
13 isPrime = false;
14 i++;
15 }
16
17 if (isPrime)
18 System.out.println(num + " is a prime number");
19 else // !isPrime
20 System.out.println(num + " isn't a prime number");
21
22 }
23 }
This is the simplest way to calculate if an integer n is probably a prime:
public static boolean isPrime (int n) {
if (n < 2) return false;
BigInteger bigInt = BigInteger.valueOf(n);
return bigInt.isProbablePrime(100);
}
You can insert this function call in a loop where you can pass a new number every iteration. I am using the implementation of BigInteger provided by Java to do the calculation, rather than writing my own. UNLESS this is a homework and you are required to write your own algorithm, I would use this solution.
This base method can then be used for calculating other types of prime numbers. A complete answer can be found here.
UPDATE:
The int parameter in BigInteger.isProbablePrime(int) is a measure of the uncertainty that the caller is willing to tolerate. The larger the number, the "slower" it executes (but the more certain it is). Also, going back to the original question (already answered in the OP's comments section):
why do I need to divide the input number by 2 (line 10), and not just
let the loop run its course till the value of the input number
achieved.
This is an optimization that will make your evaluation run twice as fast. For example, suppose an evaluation of n integers take 10 minutes to complete, excluding even numbers should take half the time. That's a significant improvement. Although you should not optimize prematurely, these sort of optimizations should be done right from the get go. Basically, we all know that even numbers are not prime, so why evaluate it? You want to evaluate unknowns. In my solution, I only evaluate values greater than 2 because by definition, values less or equal to 2 are not prime. I am merely solving that by definition or by mathematical properties.
As mentioned in the comments, dividing by 2 is a simplest optimization to reduce the number of checks, however, existing code has a few issues (e.g. returning true for 0 and 1 which are NOT prime numbers) and may be further optimized:
break/end the loop as soon as isPrime is set to false
skip even numbers by incrementing by 2
calculate until i * i <= num
If this limit is reached, it means that no factor i of num has been found in the range [2, num/i], therefore by definition of the prime numbers, all the remaining numbers in the range [num/i, num] are neither the factors of num, and therefore num is prime.
Scanner sc = new Scanner(System.in);
System.out.println("Enter a number");
int num = sc.nextInt();
boolean isPrime = num > 1 && (num % 2 != 0 || num == 2);
int i = 3;
while (isPrime && i * i <= num) {
if (num % i == 0)
isPrime = false;
i += 2; // skip even numbers
}
if (isPrime)
System.out.println(num + " is a prime number");
else
System.out.println(num + " isn't a prime number");
More optimizations are possible if the divisibles of 3 (except 3) are excluded similar to the exclusion of even numbers, then the search continues from 5 and the candidates for primality comply with 6n ± 1 rule (e.g., 5 = 6 - 1, 7 = 6 + 1, 11 = 12 - 1, 13 = 12 + 1, etc.):
boolean isPrime = num > 1 && (num % 2 != 0 || num == 2) && (num % 3 != 0 || num == 3);
int i = 5;
int d = 2;
while (isPrime && i * i <= num) {
if (num % i == 0)
isPrime = false;
i += d; // check only non-even numbers
d = 6 - d; // switch 2 to 4 and back to 2
}
assume num >=0, base is between 2 and 10;
convert(13, 2) returns "1101"
Here is my code so far i get StackOverFlow error
public String convert(int num, int base) {
if (num < 0 || base < 2 && base >10) {
return"";
}
return convert(num / base, base) + (num % base);
}
Similar to what #saka1029 said about num < 0 needing to be num <= 0 and return ""; needing some attention when num=0, you have && base > 10 rather than || base > 10. You're essentially saying "if our number is negative (impossible given that the starting num is at least 0) or the base is less than two AND greater than 10 (also impossible, a number cannot be less than two and greater than 10), then return an empty String.
You're getting a StackOverflow error because your recursive function is an infinite loop. num cannot be less than 0 and base cannot be both less than two and greater than ten at the same time.
I am having trouble getting this method, which converts an integer from binary to decimal, to work properly. The main problem I have found is that with binary numbers that end in 0, the last 0 is ignored by the program. For example, if I input 1010, the program would return 5 instead of 10. Below is my method for this conversion.
public int toDecimal(int inBase2){
int num = 0;
if(inBase2 < 0){
num = -1;
return num;
}
if(inBase2 == 0 && num == 0){
return num;
}else{
num = inBase2 % 10 * (int)(Math.pow(2, Math.log10(inBase2)));
return num + toDecimal(inBase2 / 10);
}
}
How would I go about fixing the program in a way that allows it to read the final 0 in the binary integer correctly?
You're doing the calculation the wrong way round. The least significant digit in the binary number is treated as though it's the most significant. So effectively, 1010 returns the result for 0101. Right now, the first digit you process, in the ones place, is multiplied by Math.pow(2, Math.log10(inBase2)), and given the most weight. Instead, you should multiply the results of the recursive function, so later calls (which represent higher value digits) are multiplied more. Example
public int toDecimal(int inBase2){
int num = 0;
if(inBase2 < 0){
num = -1;
return num;
}
if(inBase2 == 0 && num == 0){
return num;
}else{
num = inBase2 % 10;
return num + 2 * toDecimal(inBase2 / 10);
}
}
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.
I'd like to create a program wherein a user will type a number and the program will tell if it is divisible by 3 or not. But %, /, +, * can't be used in the program. Anybody here got some ideas how to do that?
public static void main(String[] args) {
String number = "123456";
int sum = 0;
for (char c : number.toCharArray()) {
sum = sum - (0 - c) - '0';
while (sum >= 3) {
sum -= 3;
}
}
System.out.print("divisible by 3? ");
System.out.println(sum == 0);
}
Alternatively you can keep subtracting 3 until your number is either 0 (divisible by 3) or <0: not divisible by 3.
ps: it needs to be adapted if you want to deal with negative numbers
easy peasy...
boolean divisibleBy3(int n) {
return (""+n).matches("([0369]|[147]([0369]|[147][0369]*[258])*([" +
"258]|[147][0369]*[147])|[258]([0369]|[258]" +
"[0369]*[147])*([147]|[258][0369]*[258]))*");
}
A number is divisible by there if the sum of all the digits is also divisible by 3. You can iterate the process until you have a number smaller than 10 and compare it which known divisors (3,6 and 9)
Since it is most likely a game or homework and you can use + you can simple use minus two times: a - - b is equivalent to a + b
Assuming you can use the - operator then
bool divBy3(int n)
{
while (n >= 0)
{
n -= 3;
}
return n == 0;
}
This will return true if n is exactly divisible by 3, false otherwise. Note that this is really inefficient! Using the % operator would be far better.
Divisibility by 3 in binary representation is like divisibility by 11 in decimal (10+1): sum of digits in even places minus sum of digits on odd places is in turn divisible by 3 (maybe 0).