Prime Number checker is not working - java

This is the code for a function that is supposed to return true if the input is prime and returns false if it is not.
This is how I intended for it to work: lets say that y = 7, the loop starts with n=1. Since 1(n) is less that 7(y) the loop can iterate. The program checks if y divided by n has a remainder of 0, meaning that n is a factor of y. If it is true, then it checks to see if the factor does not equal 1 or y (7), because if they dont then that means that y has more factors other than its self and 1, meaning that it is not prime, so it should automatically end the function and return false. but since 7 has only two factors, 1 and 7, and they either equal 1 or itself (y) then after the end of the loop, it should return true.
I don't understand why it isn't working.
public static boolean checkIfPrime(long y) {
for ( long n =1L; n <= y; n++) {
if(y%n == 0) {
if( n != 1L || n != y) {
return false;
}
}
}
return true;
}

With a few optimizations the code will be like this
static boolean isPrime(long n){
long lim = (long) Math.sqrt(n);
if(n%2 == 0 && n != 2)
return false;
for (int i = 3; i <= lim; i=i+2)
if(n%i == 0)
return false;
return true;
}
This code:
checks if the number is even and different from 2 (all even numbers
except 2 are compound).
next iterates from 3 to sqrt(n), thats because to prove a number is
prime you don't need to check all the dividers (if you don't believe
me try, and if still don't believe use n/2 wich is enough but not the
minimum value).
For loop pace start from 3 and add 2 in each iteration getting only odd numbers as divder (we first checked that it wasn't an even number).

Remove equal to operator in n <= y. Start your loop from 2. It must be like this. ( long n =2; n < y; n++)

For what you are trying to achieve, pseudo code in my opinion should look like this:
set a flag = true;
Loop from 2 to y-1{
if(y%n==0){
flag = false
break; // Very important
}
}
check flag condition & return (if some othe computation is required) or just return flag
if( n != 1L || n != y) : is adding a check condition unnecessarily to every iteration. try to avoid it.
Why use a flag instead of direct return statement ? Just a preference, a direct return definitely would work in this case.

Related

Strange behavior from println

I have not coded in Java in a while. I am finding the first 100 primes that is also a palindrome, now when I run the following code:
public class PalindromPrime {
/**
* Main: Prints out the first 100 PalindromPrimes in tabular format
*/
public static void main (String[] args){
int num = 0;
int myNumber = 2;
int lineCounter = 0;
while(num < 100){
if(isPrime(myNumber)){
num++;
if(lineCounter % 10 == 0){
System.out.print("\n");
}
System.out.println(myNumber);
//System.out.printf("%5d", myNumber);
lineCounter++;
}
myNumber++;
}
}
//Checks if the number is a prime number
public static boolean isPrime(int myNumber){
for(int i = 0; i <= myNumber / 2; i++){
if(i % 2 == 0){
return false;
}
}
return true;
}
}
Java gives me output that frankly does not make any sense to me?? Can someone explain this to me?
-2147483648
-2147483647
-2147483646
-2147483645
-2147483644
-2147483643
-2147483642
-2147483641
-2147483640
-2147483639
-2147483638
-2147483637
-2147483636
-2147483635
-2147483634
-2147483633
-2147483632
-2147483631
-2147483630
-2147483629
-2147483628
-2147483627
-2147483626
-2147483625
-2147483624
-2147483623
-2147483622
-2147483621
-2147483620
-2147483619
-2147483618
-2147483617
-2147483616
-2147483615
-2147483614
-2147483613
-2147483612
-2147483611
-2147483610
-2147483609
-2147483608
-2147483607
-2147483606
-2147483605
-2147483604
-2147483603
-2147483602
-2147483601
-2147483600
-2147483599
-2147483598
-2147483597
-2147483596
-2147483595
-2147483594
-2147483593
-2147483592
-2147483591
-2147483590
-2147483589
-2147483588
-2147483587
-2147483586
-2147483585
-2147483584
-2147483583
-2147483582
-2147483581
-2147483580
-2147483579
-2147483578
-2147483577
-2147483576
-2147483575
-2147483574
-2147483573
-2147483572
-2147483571
-2147483570
-2147483569
-2147483568
-2147483567
-2147483566
-2147483565
-2147483564
-2147483563
-2147483562
-2147483561
-2147483560
-2147483559
-2147483558
-2147483557
-2147483556
-2147483555
-2147483554
-2147483553
-2147483552
-2147483551
-2147483550
-2147483549
Why is it a bunch of negative values??
It is not println that is at fault. It is the logic in your isPrime method.
The number never returns true until the number increments and gets integer overflow, wrapping around to the most negative number, and then the test in the for loop always fails so the function always returns true.
The problem seems to be in the IF statement in the isPrime method.
You are currently referencing i not the number itself.
Change to:
if(**myNumber** % 2 == 0){
return false;
}
Output: 3, 5, 7, 9, ..
The isPrime method needs to be corrected..
public static boolean isPrime(int myNumber) {
for (int i = 2; i < (myNumber / 2) + 1; i++) {
if (myNumber % i == 0) {
return false;
}
}
return true;
}
Now for explanation of the problem...
In your code, instead of checking if number is divisible by index (myNumber % i), you are mistakenly just dividing the index i by 2 (i % 2 == 0) and are checking if it is 0. And since i is always starting count from 0, and the for condition is always satisfied for all positive numbers (i <= myNumber / 2), the loop always starts and returns false as the condition (i % 2 == 0) is always met.
Once myNumber in your main function finally cycles till Integer.MAX_VALUE and then reaches -ve numbers, your condition for loop i <= myNumber / 2 is finally not getting satisfied, and you are getting a true back from the function.
Hence essentially you are printing the 100 numbers counting backwards from Integer.MIN_VALUE
Hope this clarifies. I am sure you were getting results after a wait too..

Not changing boolean

I have a method for testing if a number is a prime number. I have tested the method with 8445, which is not prime because it can be divided by 3. Although the for loop has the 3 as you can see in console, it prints true. That println is in the main method of which I did not take a picture.
public boolean Primzahlerkennen(int i)
{
boolean bool = true;
for (int a = 2; a < i; a ++) {
if (i % a == 0)
bool = false;
else
a++;
if (a==3){
System.out.println("here "+a);
System.out.println(8445%3);
}
}
return bool;
}
Why doesn't the value change to false although 8445 % 3 == 0?
The issue is that you increment a twice, once in the for statement and once in the body of the loop itself.
This causes your loop to skip some divisors (three being one of them).
Further suggestions:
Give your boolean variable a name that reflects its purpose (and not bool).
You don't need to check even divisors other than 2 since none of them are prime.
You can stop the loop at sqrt(i) (figuring out why this is correct is left as an exercise for the reader).

isEvenSubset did not return 1

Here is the Question: An integer is defined to be an even subset of another integer n if every even factor of m is also a factor of n. For example 18 is an even subset of 12 because the even factors of 18 are 2 and 6 and these are both factors of 12. But 18 is not an even subset of 32 because 6 is not a factor of 32.
This is a University's sample question; the question, explicitly, states: No additional data structures including arrays allowed - therefore, please consider that too while providing answer. Thank you.
Here is my answer code:
public class IsEvenSubset {
public static void main(String[] args) {
System.out.println(isEvenSubset(18,12));
}
private static int isEvenSubset(int m, int n){
for(int i=2;i<=m;i++){
int count=0;//reset count in each round
if(m%2==0 && m%i==0){
for(int j=2;j<=n;j++){
if(n%2==0 && n%j==0){
if(i==j)count++;
}
}
if(count==0)return 0;
}
}
return 1;
}
}
This code didn't work as desired. Please help me figure out where did I do wrong?
You are checking whether m and n are even instead of whether their factors are even. Besides, the inner loop is not needed, just find all the even factors of the first number and check whether all of them are also factors of the second number.
private static boolean isEvenSubset (int m, int n)
{
for(int i = 2; i < m; i++){ // note that I don't consider m itself to be a factor of m
if (i % 2 == 0 && m % i == 0 && n %i != 0){ // i is an even factor of m but
// not a factor of n, so return false
return false;
}
}
return true; // all the even factors of m were also factors of n
}
isEvenSubset(18,12) returns true and isEvenSubset(18,32) returns false.

Java HashSet (Long vs Integer)

I was solving this problem, (41 from Project Euler), where I noticed that contains method of HashSet is working differently for Long as compared to Integer (I might be wrong here, please correct me if I am).
The question is -
We shall say that an n-digit number is pandigital if it makes use of
all the digits 1 to n exactly once. For example, 2143 is a 4-digit
pandigital and is also prime.
What is the largest n-digit pandigital prime that exists?
My code for checking whether the number is Pandigital or not is -
private static boolean isPan(Long n) {
HashSet<Long> list = new HashSet<Long>();
int count = 0;
while(n != 0){
list.add(n%10);
count++;
n /= 10;
}
for(int i = 9; i>count; i--){
if(list.contains(i)) return false;
}
for(int i = 1; i<= count; i++){
if(!list.contains(i)) return false;
}
return true;
}
This code gave me an infinite loop. So, I changed my code like this -
private static boolean isPan(Long n) {
HashSet<Integer> list = new HashSet<Integer>();
int count = 0;
while(n != 0){
list.add((int) (n%10));
count++;
n /= 10;
}
for(int i = 9; i>count; i--){
if(list.contains(i)) return false;
}
for(int i = 1; i<= count; i++){
if(!list.contains(i)) return false;
}
return true;
}
I just changed, HashSet<Long> to HashSet<Integer> and list.add(n%10) to list.add((int) n%10).
This gave me the correct answer, 7652413. So, can anyone explain why the contains method works differently for Long when compared to Integer?
contains(Object o) method doesn't work different for Long vs Integer. It works exactly the same, i.e.
Returns true if this set contains the specified element. More formally, returns true if and only if this set contains an element e such that (o==null ? e==null : o.equals(e)).
Notice however that method accepts Object as parameter type, not E. That means you can call it with any type of object. Of course, any object type other than E would cause it to return false, since equals() would fail for objects of different types (with some exceptions).
So, when you call contains(x), and x is a primitive, it will be auto-boxed, based on the type of x, not on the type of E. So if x is an int and E is Long, it'll always return false.
It is not contains() that suddenly works different, when you change Long to Integer. It is your code that works different, by correctly matching the type of value passed to contains() to the type of elements in the collection.
UPDATE
Your code is not very efficient:
It takes a Long as a parameter, but max n is by nature 9, and and int can store 9-digit numbers without overflow, so use of Long, and use of boxing, is unnecessary.
It allocates a new HashSet for every value being checked, and autoboxes every digit found, plus 9 times for the contains() calls.
Instead, this can be done using bit-manipulation, since as 32-bit int value can easily store 10 boolean values (flags) indicating whether a digit was present.
The code below will establish two bit-masks, found and expected, which will indicate whether a digit is found, and whether a digit was supposed to be found. Since solution should only use digits 1-n, we'll claim digit 0 is present and expected (makes logic simpler, not having to do special checks for 0).
If a digit is presented twice (or digit 0 is presented once), another expected digit will be missing, and found will not equal expected.
private static boolean isPandigital(int number) {
int found = 1, expected = 1;
for (int n = number; n != 0; n /= 10, expected = (expected << 1) | 1)
found |= 1 << (n % 10);
return (found == expected);
}
If you want your code run correctly,see your code whose list is HashSet<Long>:
for(int i = 1; i<= count; i++){
if(!list.contains(i)) return false;
}
you can change the type of variable i to long,or change if(!list.contains(i)) return false; to the if(!list.contains(Long.valueOf(i))) return false;
Because of the contains will check element in existence by the element's method equals.In above code,the variable i is auto-boxed to Integer instance,because the variable i is primitive int.
And see the Integer equals:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
but your list element's type is Long,so the line if(!list.contains(i)) return false; will return false always.

Can anyone see where the infinite loop in my program is?

The purpose of this program is to find the smallest number evenly divisible by all integers 1 through 20. I know it could be made more efficient, but I'm not interested in optimizing it right now. When I execute the program, it seems to hang forever, which leads me to believe that there's an infinite loop somewhere. I can't seem to find it though. I'm not sure what part of the code is causing the problem and it's relatively concise, so I'll post it all here.
public class Problem5{
public static void main(String[]args){
boolean notFound = true;
while(notFound){
int n = 20;
if(testDivide(n)){
System.out.println(n);
notFound = false;
}
else
n++;
}
}
private static boolean testDivide(int target){
for(int i = 20; i > 0; i--){
if(target % i != 0)
return false;
}
return true;
}
}
If anyone can help me out with this, I'd appreciate it a lot.
Additional Information: The program also never outputs any numbers, which leads me to believe that if(testDivide(n)) is never evaluating to true.
You are initializing the value of n inside your while loop to 20, since n is always 20 for testDivide(20), which will always return false since 20 % 19 != 0 returns false. Hence remove int n = 20 from your while loop.
boolean notFound = true;
while(notFound){
int n = 20;
should be
boolean notFound = true;
int n = 20;
while(notFound) {
your for loop makes sure you return false, and then your while loop always sets i to 20 this is your infinite loop.
See the while loop:
while(notFound){
int n = 20;
if(testDivide(n)){
System.out.println(n);
notFound = false;
}
else
n++;
}
When the while loop is executed first, the value of n is set to 20.
the test divide returns false.
The value of n is decremented to 19.
The loop executes again
The value of of n is reinitialized to 20.
This is the problem initialize n outside the while loop.

Categories

Resources