Using java to find Happy Numbers: Nested while loop loops indefinitely - java

My assignment asks for a command-line input to be put through nested while loops to find if a number is a happy number or not. So far I have this:
int i = 0;
int sum = 0;
int dig2, dig1, dig3, dig4, dig1next, dig2next, dig3next;
int digit1sum, digit2sum, digit3sum;
happyNumber = number;
while (i < 500){
while (happyNumber > 0){
while (sum!=1){
dig3 = happyNumber / 100;
dig2 = happyNumber % 10;
dig1 = happyNumber / 10;
dig2next = dig2 % 10;
dig1next = dig1 % 10;
dig3next = dig3 % 10;
digit1sum = dig1next * dig1next;
digit2sum = dig2next * dig2next;
digit3sum = dig3next * dig3next;
sum = digit1sum + digit2sum + digit3sum;
happyNumber = sum;
}
System.out.println("It is a happy number.");
System.exit(0);
}
i++;
System.out.println(i);
System.exit(0);
}
I set i<500 so when i++ reaches 500, the loop should stop. I've pretty much tried putting i++ in every section of the code possible, it never works. what am i doing wrong here?
also: i am not allowed to use for loops or do-while loops on this assignment. i have to use nested while loops only
Happy number: Starting with any positive integer, replace the number by the sum of the squares of its digits, and repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1(how long the loop will be: 500).

After a quick glance at your code:
while (sum!=1)
....
sum = digit1sum + digit2sum + digit3sum;
happyNumber = sum;
This while test is likely to be always true -> infinite loop -> stack overflow

You will never get out of your innermost while-loop in case of a number that loops endlessly (it is by no means stopped by the 500- limit and your logic is wrong here).
Secondly, something to think about:
digit1sum = dig1next*dig1next;
digit2sum = dig2next*dig2next;
digit3sum = dig3next*dig3next;
these (digitxsum) will always be positive.
sum = digit1sum + digit2sum + digit3sum;
sum will therefore always be positive
happyNumber = sum;
happynumber will always be positive
while (happyNumber > 0)
what is this for?

Related

Calculate Average of Previous Loop - Java

So, I am working on this code for my AP Computer Science class, and I ran into a problem.
First, here is my code:
//loop counters
int counterOne = 0;
int counterElse = 0;
int loop = 1;
int iNum = 1000;
//create file
PrintWriter outFile = new PrintWriter(new File("newFile.txt"));
for (int counter = 1; counter <= iNum; counter++)
{
while (loop >= 1)
{
Random rand = new Random();
int iRand = rand.nextInt(5)+1;
if (iRand != 1)
{
counterElse++;
loop++;
}//end of if of if-else
else
{
counterOne++;
loop = 0;
}//end of else of if-else
}//end of while loop
int tries = counterElse+counterOne;
//int average = (tries + prevTriesSum) / counter
System.out.println("It took " + tries + " try/tries to win!");
//outFile.println("It tool an average of " + average + " tries to win.");
}//end of for loop
How do I calculate the average of the trials? As you can see from the end of my code, I commented out a line that I would want to calculate the average. This is because I don't know how to calculate prevTriesSum, which represents the sum of all of the other trials. Here is an example: Assume the loop runs six times, and with the first run, it takes 3 tries, 5 on the second run, 7 on the third, 11 on the fourth, 2 on the fifth, and 4 on the sixth (the most recent one. now tries = 4).
I would want prevTriesSum to equal 3 + 5 + 7 + 11 + 2 + 4.
How do I get the program to calculate that?
Your average is computed in integer arithmetic which means any fractional part is discarded. Consider using a floating point type for the average, and prefix the right hand side of the assignment with 1.0 * to force the calculation to occur in floating point.
You must not reinitialise the random generator in the loop, else you ruin its statistical properties. Do it once before you enter the loop.
Before the while loop, add
int prevTriesSum = 0;
Replace your commented int average = line with
prevTriesSum += tries;
And after the for loop add
double average = (prevTriesSum + 0.0) / counter;
outFile.println("It tool an average of " + average + " tries to win.");
As for the random number generator, Bathsheba is correct. You must move that above the for loop. Just move the declaration.
You'll also need to change your for loop slightly. As it stands, it will equal 1001 when the for loop terminates. Change it as follows:
for (int counter = 0; counter < iNum; counter++)
This will ensure that your average calculation is correct.

can someone explain the steps to compute this equation? Java

Write a program that computes the following equation.
100/1+99/2+98/3+97/4+96/5...3/98+2/99+1/100
I am not asking for a solution. Yes this is a homework problem, but I am not here to copy paste the answers. I asked my professor to explain the problem or how should I approach this problem? She said "I can't tell you anything."
public static void main(String[] args){
int i;
for(i = 100; i >= 1; i--)
{
int result = i/j;
j = j+1;
System.out.println(result);
}
}
You can try to observe a "trend" or "pattern" when solving questions of this type.
Given: 100/1+99/2+98/3+97/4+96/5...3/98+2/99+1/100
We derived: Numerator/Denominator, let's call it n divide by d (n/d)
Pattern Observed:
n - 1 after every loop
d + 1 after every loop
So, if you have 100 numbers, you need to loop 100 times. Thus using a for-loop which loops 100 times will seemed appropriate:
for(int n=0; n<100; n++) //A loop which loops 100 times from 0 - 100
To let n start with 100, we change the loop a little to let n start from 100 instead of 0:
for(int n=100; n>0; n--) //A loop which loops 100 times from 100 - 0
You settled n, now d needs to start from 1.
int d = 1; //declare outside the loop
Putting everything together, you get:
int d = 1;
double result = 0.0;
for (int n=100; n>0; x--)
{
result += (double)n/d; //Cast either n or d to double, to prevent loss of precision
d ++; //add 1 to d after every loop
}
You are on the right track. You need to loop like you've done, but then you need to SUM up all the results. In your example you can try:
result = result + i/j;
or
result += i/j;
Note that the declaration of result needs to be outside the loop otherwise you are always initializing it.
Also think about the division (hint), you are dividing integers...
What you have is a series.
There is more than one way to define a series, but all things being the same it's more intuitive to have the index of a series increase rather than decrease.
In this case, you could use i from 0 to 99.
Which in java can be:
double sum = 0;
for (int i = 0; i < 100; i++) {
sum += (100 - i) / (double) (1 + i);
}
if you want the result in the same format then do :
int j = 100;
double sum=0;
for (int i = 1; i <= 100; i++) {
sum += ((double) j / i); // typecast as least one of i or j to double.
System.out.print(j + "/" + i+"+");
j--;
}
// here print the sum

Java program terminating without error?

I'm trying to make a program that finds the largest palindrome that is a product of two 3-digit numbers. This is what I have right now (I am new to programming):
int num1 = 0;
int num2 = 0;
int product = 0;
int tempProd1 = 0;
int tempProd2 = 0;
int tempProd3 = 0;
int tempProd4 = 0;
int tempProd5 = 0;
int tempProd6 = 0;
String prodCheck1 = "";
String prodCheck2 = "";
while (num1 < 1000){
while (num2 < 1000){
product = num1 * num2;
prodCheck1 = Integer.toString(product);
tempProd1 = product % 10;
product = product / 10;
tempProd2 = product % 10;
product = product / 10;
tempProd3 = product % 10;
product = product / 10;
tempProd4 = product % 10;
product = product / 10;
tempProd5 = product % 10;
product = product / 10;
tempProd6 = product % 10;
product = product / 10;
prodCheck2 = "tempProd1" + "tempProd2" + "tempProd3" + "tempProd4" + "tempProd5" + "tempProd6";
if (prodCheck1 == prodCheck2){
System.out.println(prodCheck1);
}
num2++;
}
num1++;
}
Thing is, every time I try to run it, it terminates without an error. Could someone explain what I'm doing wrong?
Edit: Thanks everyone, finally fixed it. The answer is 853358, if anyone was wondering.
Edit: Actually, the number was 906609.
One thing I noticed immediately is that after the first iteration of the inner loop, num2 is 1000 and so the inner loop will just do nothing in the remaining 999 iterations of the outer loop. You have to reset num2 to 0.
Also consider using "for" loops instead; they're designed to prevent this kind of mistake:
for (int num1=0; num1<1000; num1++) {
...
}
Another problem is that the palindrome check is wrong. You cannot compare Strings with == (it tests for object identity, not string equality -- you'd have to use equals() instead). But even that is wrong because prodCheck2 is "tempProd1tempProd2..." and doesn't contain the actual numbers. The easiest way to check for a palindrome would be:
if (tempProd1 == tempProd6 && tempProd2 == tempProd5 && tempProd3 == tempProd$) {
...
}
Equals method for strings
There are several issues here. First == should not be used to compare strings. You should use string.equals(otherString);
Contatinating words
Second you appear to be combining words when you want to combine values
prodCheck2 = "tempProd1" + "tempProd2" + "tempProd3" + "tempProd4" + "tempProd5" + "tempProd6;
will give
prodCheck2 = "tempProd1tempProd2tempProd3tempProd4tempProd5tempProd6";
always. The fact that those words happen to have the same name as some of your variables makes no difference to java.
There are many better ways to concatenate integers. But the easiest is probably as follows
prodCheck2 = tempProd1 + "" + tempProd2 + "" +tempProd3 + "" +tempProd4 + "" +tempProd5 + "" +tempProd6";
Using while when for would be better
while (num1 < 1000){
while (num2 < 1000){
......
num2++;
}
num1++;
}
This code never decreases num2, which means num2 goes 1->1000 for num1=0 and then stays at 1000 from then on. I'm guessing this isn't what you want. We could fix the while loop but really this is what a for loop is for
for(int num1=0;num1<1000;num1++){
for(int num2=0;num2<1000;num2++){
//code as before, no need to inciment or reset num1 or num2 inside the loop
}
}
Issues that don't break your code
You're declaring all your variables with very large scope. For example tempProd1 is declared outside all the loops depite only being needed inside the inner loop. Declare variables in the smallest scope possible. This will catch bugs like those we've found here. Critically num2 couldn't have accidently been made non resetting if you'd delared it within the first loop
if (prodCheck1 == prodCheck2){
System.out.println(prodCheck1);
}
is a comparison that is based solely on the identity equality of prodCheck1 and prodCheck2. Rewrite that code as:
if (prodCheck1.equals()){
System.out.println(prodCheck1);
}
to use value equality that will return true for identical strings.

Simple program using loops (Beginning Java)

I have to write a program using loops that calculates the sum of all odd numbers between a and b (inclusive), where a and b are inputs.
I made this (below) and it works fine, but I noticed one problem with it: when i enter a larger number followed by a smaller number for the inputs, it returns 0, but when i enter the smaller number first it works perfectly. Any quick fixes for this? :)
import java.util.Scanner;
public class ComputeSumAAndB
{
public static void main (String[] args)
{
Scanner in = new Scanner(System.in);
System.out.print("Please enter 2 integers: "); //prompts user for ints
int a = in.nextInt();
int b = in.nextInt();
int sum = 0;
for (int j = a; j <= b; j++)
{
if (j % 2 == 1)
sum += j;
}
System.out.println("The sum of all odd numbers (inclusive) between " + a + " and "+ b + " is " + sum);
}
}
int temp;
if(a > b) {
temp = a;
a = b;
b = temp;
}
Put this right before your for loop starts.
The if checks whether a (the first number entered) is larger than b. If it is, it swaps a and b. Now your for loop will always start with the smallest number and iterate up to the larger number (because after this if, a will always be the smaller number).
Using this method has the added side effect of making your output make sense. Your output will now always say: "between [smaller number] and [larger number]".
rolfl's answer is more elegant and works perfectly fine, but when the user enters the larger number first, your output may look kind of weird: "between [larger number] and [smaller number]", etc.
You can get the smaller and larger inputs by using the Math.min() and Math.max functions....
for (int j = Math.min(a,b); j <= Math.max(a,b); j++) {
if (j % 2 == 1) {
sum += j;
}
}
It's not working because A is larger than B in the for loop, you have it iterate while A is less than or equal to B.
You could do what nhgrif says but it's changing your data.. But he is correct.
That's because you are first expecting for the a input (inferior limit) and then the b (superior). When your program reaches the for, j = a so the condition a <= b is False, if the first input is larger. In other words it never enters the for loop.
Actually you should do the following 2 things:
1 It is just just like rolfl mentioned above. You need to put the min and max in the right place in loop.
for (int j = Math.min(a,b); j <= Math.max(a,b); j++)
{
if (j % 2 == 1) {
sum += j;
}
}
2 Use if (j % 2 == 1) it is not enough to check whether the num is odd.
e.g.
a = -5, b =0;
What will be the result?
int sum = 0;
for(int j=-5;j<0;j++)
{
if(j%2 == 1)
{
sum+=j;
}
}
The value for sum will be 0.
We need to change the condition to if(!(j%2 == 0)) Then you will get the expected result.
That's because you are first expecting for the a input (inferior limit) and then the b (superior). When your program reaches the for, j = a so the condition a <= b is False, if the first input is larger. In other words it never enters the for loop.

Java simple while loop confusion

I am having trouble with this simple loop for a uni lab. It wont stop looping until I put in a number over a thousand. I can't see where I have gone wrong on such a simple loop.
I have meant to have written a simple method that will loop through adding numbers until the number is greater than 100 and then once it has reached 100 or greater it will output the total.
public void adder2(){
int sum = 0;
int number = 0;
while(number < 100){
sum = sum + number;
number = getNumber();
}
System.out.println("The result is " + sum);
}
Try this:
while (sum < 100 && number < 100) { ...code as above... }

Categories