I have to write a method that returns/prints the odd numbers between 1 and 100, but I have to use another method, which checks whether a given integer is odd or not:
static boolean isOdd(int c) {
boolean d;
d = c % 2 != 0;
return d;
}
I'm guessing that I have to use either a for- or while-loop (probably can be done with both?), but I think what I'm really struggling with is "connecting" both methods. So the numbers actually run through isOdd() which determines whether they are odd.
I've tried these two options so far, but they're not working.
Option 1:
static void func1() {
int number = 1;
while (number < 100 && isOdd(number)) {
System.out.println(number);
number = number + 1;
}
}
Option 2:
static void func1() {
int i;
for (i = 1; i < 100; i++) {
isOdd(i);
}
System.out.println(i);
}
Your attempt #1 is closer to your goal ;)
you are right that you can use while and for (and probably other kinds of processing multiple numbers, but that just for the sake of completeness, forget it for now)
your println (or print) should be within the loop because you want to print more than just one number.
in you current attempt #1 you end your loop with the first odd number: 1 This doesn't count up very far ;)
So you have to use an if inside your loop where you check the result of isOdd(number) and only print if it's odd.
But the loop has only the upper bound limit as condition (number < 100) as you want to check all the numbers.
Smartass hint (try it only after your program works fine): if you count up by 2 instead by 1 (number = number + 2;), your program will only need half the time - and you could even skip the isOdd check ;-)
I'm guessing that I have to use either a for- or while-loop (probably can be done with both?)
Yes. for-loops are just syntactic sugar for special while-loops:
for (init_stmt; cond; incr_stmt) body_stmt;
is equivalent to
init_stmt;
while (cond) {
body_stmt;
incr_stmt;
}
Let's first write this using a for-loop.
for-loop
for (int i = 1; i < 100; i++)
if (isOdd(i))
System.out.println(i)
Note that we can (and should!) do the declaration of i as int in the for-loop initializer.
Now, we may translate this to an equivalent while-loop:
while-loop
int i = 1;
while (i < 100) {
if (isOdd(i))
System.out.println(i);
i++;
}
Mistakes in your attempts
Attempt 1
You've mistakenly included the check in the condition (rather than using it in an if inside the loop body); the first even number (2) will cause the loop to terminate.
Attempt 2
You're not even using the return value of isOdd here. You're unconditionally printing i after the loop has terminated, which will always be 100.
The ideal implementation
Ideally, you'd not be filtering the numbers; you'd directly be incrementing by 2 to get to the next number. The following loop does the job:
for (int i = 1; i < 100; i += 2)
System.out.println(i);
Related
I assume that if I can't convert my while loop into a for loop, then I don't fully understand the concepts here. Here's my working while loop:
(I am trying to implement a program, which calculates the sum 1+2+3+...+n where n is given as user input.)
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Enter a number: ");
int number = Integer.valueOf(scanner.nextLine());
int sum = 0;
int i = 0;
while (i < number) {
i++;
sum += i;
}
System.out.println(sum);
I was looking at this user's answer here: https://stackoverflow.com/a/36023451/11522261
and tried to implement it, but it's not working.
.....
for (i = 0; i < number; i++){
sum += i;
}
System.out.println(sum);
It looks like the conditions of For Init expression statement and ForUpdate are set right, but I'm having trouble understanding the differences here.
Also, it looks like this exercise is trying to teach loops to solve iterative problems. But I suspect that this isn't helping me practice recursion. Perhaps there is a recursive solution to this problem which would be better. Just thinking out loud here. Thanks!
The difference is that in your while loop, you're incrementing i before adding it to sum, but in your for loop, it's after.
If the while is producing the right result, you can adjust your for by starting at 1 instead of 0 and continuing while <= number instead of < number.
For completeness, here's how your current for loop works:
i = 0
If i < number is not true, exit the loop; otherwise, continue to Step 3
sum += i (i is still 0)
i++
Goto Step 2
On the second pass, i < number is 1 < number so still true if number is greater than 1, so you go to Step 3, do sum += i while i is 1, then continue.
Eventually i < number isn't true anymore, and the loop exits.
For problems like this, the best approach is usually to use the debugger built into your IDE to step through the code statement by statement, looking at the values of variables as you go. That can reveal how things work really well. This article may be helpful: How to debug small programs
Since you are incrementing the value of i before adding it to sum in the while loop, the same thing needs to be done in case of for loop as well. Given below is the implementation using the for loop:
for (i = 0; i++ < number; ){
sum += i;
}
System.out.println(sum);
Use <= instead of <. This will solve Your problem, and make sure you understand why will the following code would work. I would recommand you to use a paper and pencil and start writing down the values of i and sum after every iteration.
for (i = 1; i <= number; i++) {
sum += i;
}
Is it possible to have two loops in a function?
public static void reduce(Rational fraction){
int divisorNum = 0;
int n = 2;
while(n < fraction.num){
if(fraction.num % n == 0){
divisorNum = n;
System.out.println("n: " + divisorNum);
n++;
}
}
int divisorDenom = 1;
int m = 2;
while(m<fraction.denom){
if(fraction.denom % m == 0){
divisorDenom = m;
System.out.println("m: " + divisorDenom);
m++;
}
}
}
I'm trying to get the greatest common denominator. I know this is the very long way about doing this problem but I just wanted to try having two loops. When I call this function, only the first loop gets printed and not the second. I originally had an if statement, but seeing that the second loop doesn't execute I figured that I fix this part first.
Here's my other part of the code:
public static void main(String[] args){
Rational fraction = new Rational();
fraction.num = 36;
fraction.denom = 20;
reduce(fraction);
}
Absolutely. There are no limitations
Watch your conditional test = is not quite ==
Based on your edit I suspect fraction.denom is initialized at 1 or 0
Hence you will never get in the second loop
You can have any number of loops in your function :-
1.You can have nested loops;
2.Two loops side by side.
SO,your piece of code is fine enough considering the value of n, until the conditions for loop execution are met :-
public static void ....
while(n<x){
do this
add to counter
}
while(m<x){
do this
add to counter
}
if(y==z){ // NOTE :- Here you have committed mistake, compare using ==, not by =(it will be always true else and your condition will always be met else)
print this
}
Yup. You even can have 3 if you try hard enough.
EDIT: The didactic version:
Loops, as the name suggest, are constructs that allow you to repeat blocks of code several times (post conditional loops -> until certain condition is met keep running, pre conditional loops -> if certain condition is met, keep running). This is often called "iteration". So in a typical for-loop:
for ( int i = 0; i < 10; ++i )
print(array[i]);
You can say you're "iterating" over the array 10 times.
This has nothing to do with functions. You can have several loops inside a function, or functions being called inside loops. As long as you define your "blocks" of code (with begining and ending braces) you do what you think its best.
Yes, there are no limitations when it comes to looping. You could do 1000 while loops if you wanted.
An example here could be doing something like making a square out of *...
Here's an example
for(int i = 0; i < 4; i++)
{
for(int j = 0; j < 4; j++)
{
System.out.print("*");
}
System.out.println();
}
It would look like:
****
****
****
****
I got an assignment to create a program which displays the perfect integers between one and 100. Here is the actual assignment:
Create a PerfectIntegers application that displays all perfect integers up to 100. A perfect integer is a number which is equal to the sum of all its factors except itself. For example, 6 is a perfect number because 1 + 2 + 3 = 6. The application should include a boolean method isPerfect().
I tried and came up with this:
import java.util.ArrayList;
public class PerfectIntegers {
public static boolean isPerfect(int a){
ArrayList<Integer> factors = new ArrayList<Integer>();
int sum=0;
boolean is;
for (int i=1; i<=100; i++){
double r=a/i;
if (r%1==0){
factors.add(i);
}
}for (int i=0;i<factors.size();i++){
sum+=factors.get(i);
}if (sum==a){
is=true;
}else{
is=false;
}return is;
}
public static void getInts(){
for (int i=2; i<=100; i++){
boolean is=isPerfect(i);
if (is!=false){
System.out.print(i+" ");
}
}
}
public static void main(String[] args) {
getInts();
}
}
Eclipse did not show any errors but when I try to run it, the program is terminated and I get nothing.
The problem is likely with double r, as it is not dividing properly 100% of the time.
Your factorization code is wrong. You can fix it like this:
for (int i = 1 ; i < a; i++) {
if (a % i == 0) {
factors.add(i);
}
}
One reason your old code did not work is that you misunderstood the workings of the % operator. It computes the remainder of the division of the left-hand side by the right-hand side, so r % 1 == 0 will be true for all numbers, because 1 divides everything; r % 2 == 0 is a way to detect even numbers, and so on.
The other reason is that you went all the way to 100 in search of divisors. This necessarily includes a, which automatically puts the total above the number itself, because 1 is already on the list.
Once you get this working, you could simplify the code by dropping the list of factors. Since the sum of all factors is all that you need, you might as well compute it in the factorization loop, and drop the loop that follows it:
sum = 0;
for (int i = 1 ; i < a; i++) {
if (a % i == 0) {
sum += i;
}
}
dasblinkenlight has already provided the correct answer. Let me just add that since this seems to be a (potentially graded) assignment you might consider refactoring the getInts() method as well.
boolean is=isPerfect(i);
if (is!=false){
System.out.print(i+" ");
}
is actually equal to
if (isPerfect(i)){
System.out.print(i+" ");
}
since isPerfect() already returns a boolean that can be used inside the condition of the if-statement.
It can be argued (even though I strongly disagree in this concrete case) that it might be more readable to first store the return value in a variable like in in the first variation. But even then you should never have to check for
if (is!=false) { //...
but should be using
if (is) { // ...
instead.
Below is one of the first programs I made (with help from the Internet) in Java. It is a program that checks if a given integer is prime or not and prompts the user with feedback. If the user input is not an integer it outputs that it is not an integer. The latter also happens when Big Integers are entered. This is the code:
import java.util.Scanner;
class BasicPrime1 {
public static void main(String[] args) {
try {
System.out.println("Enter an Integer: ");
Scanner sc = new Scanner(System.in);
int i;
int number = Integer.parseInt(sc.nextLine());
// 1 and numbers smaller than 1 are not prime
for (i = 1; number <= i;) {
System.out.println("NOT a prime!");
break;
}
// Number is not prime if the remainder of a division (modulus) is 0
for (i = 2; i < number; i++) {
int n = number % i;
if (n == 0) {
System.out.println("NOT a prime!");
break;
}
}
// I do not understand why the if-statement below works.
if(i == number) {
System.out.println("YES! PRIME!");
}
}
catch(NumberFormatException nfe) {
System.out.println("Not an integer!");
}
}
}
This program does his job, but I do not know why the part with the if-statement works. How is it possible that "i == number" gives a value of true (it prints out "YES! PRIME" when you enter a prime)? The local variable i gets incremented in the for-loop, but the if-statement is outside of the for-loop.
/edit the paragraph below is nonsense as Jim Lewis points out
Thinking about it now, the only reason I can think of that this is the case is because the == operator checks if the i-'object' and number-'object' belong to the same 'type' (i.e., have a reference to the same object). Since they both belong to the type of primitive integers this program catches the integers (other input throws a NumberFormatException which is caught and outputs "Not an integer"). The ones that are primes pass the first for-loop and then the magical if-statement gives "true" and it prints out "YES! PRIME!".
Am I on the right track?
I have improved this program by removing the magical if-statement and changing it for an if-else-statement like this: (/edit fixed problem with code thanks to answer of ajb)
boolean factorFound = false;
for (i = 2; i < Math.sqrt(number) + 1; i++) {
int n = number % i;
if (n == 0) {
factorFound = false;
break;
}
else {
factorFound = true;
}
}
if(factorFound == false) System.out.println("NOT a prime!");
if(factorFound == true) System.out.println("YES! PRIME!");
By only going up to the square root of the input number the calculation time improves (I know it can be even more improved by only checking odd numbers or using a AKS Primality Test, but that is beside the point).
My main question is why I could not improve the efficiency of the first program (with the magical if-statement) in the same manner. When I enhance the for-loop like this "(i = 2; i < Math.sqrt(number) + 1; i++)" in the first program it does no longer print out "YES! PRIME!" when you input a prime. It gives a blank. Even if my previous explanation is correct - which it is probably not - this is not explained.
You may enlighten me.
ANSWER: int i is outside of scope of for-loop and after going through the for-loop multiple times upto number the value of i will reach the value number, when we can be sure it is a prime. Furthermore, after checking the disappearing "YES! PRIME!" statement once again it turns out it is actually possible to change number in both the if-statement and for-loop to ( Math.sqrt(number) + 1 ) and have working code. So the question was based on a false premise.
i is declared outside the for loops, so its value is still in scope and available after the loop
finishes (nothing to do with comparing data types or anything like that!).
If no divisors were found, the i < number loop condition will eventually
fail, with i == number. (If the loop finds a divisor and hits the break statement,
that condition no longer holds).
When you do the sqrt optimization, the end condition of the loop is changed,
so i == number no longer holds after the loop exits, even if the number is prime.
In my opinion it would be more clear to explicitly set a flag (e.g. isPrime=0 just
before breaking out of the loop), then check that flag rather than looking at the
loop variable to see whether the loop completed or not.
// I do not understand why the if-statement below works
Explanation: Because i has been incremented until it equals number. If you stop at sqrt(number) then the if statement will always fail.
By the way I don't like using square root with integers. I like this better for a isPrime function:
if (number < 2) return false;
if (number > 2 && number % 2 == 0) return false;
for (int i = 3; i * i <= number; i = i + 2)
if (number % i == 0) return false;
return true;
I understand the concept of one having certain advantages over the other depending on the situation but are they interchangeable in every circumstance? My textbooks writes
for (init; test; step) {
statements;
}
is identical to
init;
while (test) {
statements;
step;
}
How would I rewrite the following program in the for loop? I'm having trouble setting the value for the init and the test if i rework the following program into the for loop form.
import acm.program.*;
public class DigitSum extends ConsoleProgram{
public void run() {
println("this program sums the digits in an integer");
int n = readInt("enter a positive number: ");
int dsum = 0;
while ( n > 0) {
dsum += n % 10;
n /=10;
}
}
}
int dsum = 0;
for(int n = readInt("enter a positive number: "); n > 0; n /=10) {
dsum += n % 10;
}
As I can't stop myself from writing this, so I'll point it out.
Your for loop: -
for (init; test; step) {
statements;
}
Is not identical to the while loop you posted. The init of the for loop will not be visible outside the loop, whereas, in your while loop, it would be. So, it's just about scope of the variable declared in init part of for loop. It is just inside the loop.
So, here's the exact conversion of your for loop: -
{
init;
while (test) {
statements;
step;
}
}
As far as the conversion of your specific case is concerned, I think you already got the answer.
Well, by the above explanation, the exact conversion of your while loop is a little different from the #Eric's version above, and would be like this: -
int dsum = 0;
int n = 0;
for(n = readInt("enter a positive number: "); n > 0; n /=10) {
dsum += n % 10;
}
Note that this has a very little modification from the the #Eric's answer, in that, it has the declaration of loop variable n outside the for loop. This just follows from the explanation I gave.
Beside the scope of variables declared in the initializer, there is another time when a for will exhibit different behavior, which is in the presence of a continue:
for (init; test; update) {
if(sometest) { continue; }
statements;
}
is NOT identical to
init;
while (test) {
if(sometest) { continue; }
statements;
update;
}
because in the while loop the continue it will skip update, where the for loop will not.
To show this via the starkest of examples, consider the following two loops (thanks #Cruncher):
// terminates
for(int xa=0; xa<10; xa++) { continue; }
// loops forever
int xa=0;
while(xa<10) { continue; xa++; }
+1, good question
The difference between the two is mostly eye-candy. In the one instance the one may simply read better than the other. For your example, the following is the for-loop equivalent in a single line of code. In this case, however, the while loop reads easier.
public void run() {
println("this program sums the digits in an integer");
for (n = readInt("enter a positive number: "), dsum=0; n > 0; dsum+=n%10, n/=10);
}
Yes, except for the two things:
"For" let you declare and initialize your conditions (= variables, btw - more than one variable!) in it, and then it is cleaned up automatically, as you leave the "For" cycle.
Whereas with "While" you will have to do it yourself, initialize - outside the "While", clean up - only as you leave the of visibility where your variables (for conditions) were declared.
"For" has convenient syntax (and all cleanup afterwards) for iteration over collections and arrays.
Your code I would rewrite this way:
import acm.program.*;
public class DigitSum extends ConsoleProgram{
public void run() {
println("this program sums the digits in an integer");
for(int n = readInt("enter a positive number: "), dsum = 0; n > 0; n /=10) {
dsum += n % 10;
}
}
}
Don't forget - in init you can place declaration/initialization for more than one variable.
what kind of difficulties you have,anyway
int n = readInt("enter a positive number: ");
for(n;n>0;n=n/10)
{dsum+=n%10;
}
This should work. Replace your while loop with this. Just leave the initialization part empty.
for(;n>0;n=n/10)
{
dsum+=n%10;
}