I made a class for a date and within this class lies the following declarations:
private int year;
private boolean leap = ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0));
public boolean isLeap() {return leap;}
And then (in a different file) within the main method:
String leapStr;
if (dateObject.isLeap()) {leapStr = "";}
else leapStr = "non-";
System.out.printf("Year %d is a %sleap year.", dateObject.getYear(), leapStr);
So, for some reason leapStr is never "non-", even when the year is clearly not a leap year. I have absolutely no idea what the problem could be. Any ideas?
Because the value of leap is calculated once on object creation, and at that moment year is initialized with default value of 0.
You should calculate leap in isLeap method.
You haven't initialized year hence the default value for int will be 0 , this is why yor condition is always returning true (0%400 == 0)
Related
The code works when the first year is a leap year so if I said the year was 2004 it would return 2008, but when the starting year is not a leap year, it returns nothing. How would I output that if, for ex: the given year was 2001, 2002, or 2003, the next leap year would be 2004. I know the while loop makes sense but I don't know what to put inside it. ALSO I can only use basic java formatting so no inputted classes like java.time.Year
public static boolean leapYear(int year) {
boolean isLeap = true;
if (year % 4 == 0) {
if (year % 100 == 0) {
if (year % 400 == 0)
isLeap = true;
else
isLeap = false;
} else
isLeap = true;
} else {
isLeap = false;
}
return isLeap;
}
public static int nextLeapYear(int year) {
int nextLeap = 0;
if (leapYear(year)) {
nextLeap = nextLeap + 4;
} else {
while (!leapYear(year)) {
nextLeap++;
}
nextLeap += 1;
}
year += nextLeap;
return year;
}
Granted this doesn't take much processing. But if you want to increase the efficiency of your program you might consider the following:
All leap years must be divisible by 4. But not all years divisible by 4 are leap years. So first, check for not divisible by 4. That will be 75% of the cases. In that event, return false.
if (year % 4 != 0) {
return false;
}
As you continue, the year must be divisible by 4 so just make certain it is not a century year. This will be evaluated 25% of the time and will return true 24% of the time.
if (year % 100 != 0) {
return true;
}
lastly, the only category not checked are years divided by 400. If we got here in the logic, then it must be a century year. So return accordingly. This will evaluate to true .25% of the time.
return year % 400 == 0;
Your code is broken in multiple ways:
You say: If the given year is a leap year, then the next leap year will be 4 years later. This is false. If you pass in 1896, your algorithm returns 1900, but this is wrong; whilst 1896 is a leap year, 1900 is not.
Your isLeapYear code would be miles easier to read if you early-exit. That method should have a lot of return statements and fall less indentation.
Your while loop will keep asking the same question over and over, and if you ask the same question to a stable method (and your isLeapYear method is stable), you get the same answer, resulting in an infinite loop. Presumably, you don't want while(!leapYear(year)), you want while(!leapYear(year + nextLeap)), and you don't want to increment nextLeap once more after the while loop.
in fact, your edge case of: If the stated year is already a year, add 4 - is not necessary at all. Think about it: You can just eliminate that if/else part. Your code will just be nextLeap, that while loop, and a return statement. a 3-liner, if you do right.
EDIT: I figured it out yay!
for anybody struggling w/ this, this is what worked for me :)
public static boolean leapYear(int year) {
if(year % 4 == 0)
{
if( year % 100 == 0)
{
// year is divisible by 400, hence the year is a leap year
if ( year % 400 == 0)
return true;
else
return false;
}
else
return true;
}
else
return false;
}
public static int nextLeapYear (int year) {
int nextLeap = 0;
while(leapYear(year + nextLeap) == false){
nextLeap++;
}
if(leapYear(year) == true)
nextLeap += 4;
year += nextLeap;
return year;
}
Every year that is exactly divisible by four is a leap year, except
for years that are exactly divisible by 100, but these centurial years
are leap years if they are exactly divisible by 400. For example, the
years 1700, 1800, and 1900 are not leap years, but the years 1600 and
2000 are.
- United States Naval Observatory
You can greatly simplify the function, leapYear as shown below:
public static boolean leapYear(int year) {
return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
}
Demo:
public class Main {
public static void main(String[] args) {
// Test
System.out.println(leapYear(1999));
System.out.println(leapYear(2000));
System.out.println(leapYear(1900));
System.out.println(leapYear(1904));
}
public static boolean leapYear(int year) {
return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
}
}
Output:
false
true
false
true
Then, you can use it in the function, nextLeapYear as shown below:
public class Main {
public static void main(String[] args) {
// Test
System.out.println(nextLeapYear(1999));
System.out.println(nextLeapYear(2000));
System.out.println(nextLeapYear(2001));
}
public static int nextLeapYear(int year) {
// If year is already a leap year, return year + 4
if (leapYear(year)) {
return year + 4;
}
// Otherwise, keep incrementing year by one until you find a leap year
while (!leapYear(year)) {
year++;
}
return year;
}
public static boolean leapYear(int year) {
return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
}
}
Output:
2000
2004
2004
In production code, you should use the OOTB (Out-Of-The-Box) class, java.time.Year to deal with a year.
import java.time.Year;
public class Main {
public static void main(String[] args) {
// Test
System.out.println(nextLeapYear(1999));
System.out.println(nextLeapYear(2000));
System.out.println(nextLeapYear(2001));
}
public static int nextLeapYear(int year) {
Year yr = Year.of(year);
// If year is already a leap year, return year + 4
if (yr.isLeap()) {
return yr.plusYears(4).getValue();
}
// Otherwise, keep incrementing year by one until you find a leap year
while (!yr.isLeap()) {
yr = yr.plusYears(1);
}
return yr.getValue();
}
}
Output:
2000
2004
2004
Learn more about the modern date-time API at Trail: Date Time.
It seems it not easy to get nextLeapYear() 100 % correct. Allow me to suggest a simpler way of thinking about it that will also — so I believe — make it simpler to code correctly and/or fix any bug there may be.
Declare a variable candidateLeapYear to hold a year that we don’t yet know whether will be the next leap year after year. Initialize it to year + 1 since we know that the next leap year will need to be strictly greater than year. In a loop test whether candidateLeapYear is a leap year (use the other method), and as long as it isn’t, increment by 1. When the loop terminates, candidateLeapYear holds the next leap year. Return it.
Edit: Apologize for confusing some of you, here is little more details.
I am very new to the stackoverflow. So I apologize in advance for a stupid questions.
I came across the below exercise in Udemy and my code is failing. Please help me understand why it is failing?
Description of the exercise:
Write a method shouldWakeUp that has 2 parameters.
1st parameter should of type boolean and be named barking it represents if our dog is currently barking
2nd parameter represents the hour of day and is of the type int with the name hourOfDay and has a valid range of 0-23
we have to wake up if the dog is barking before 8 or after 22 hours so that in that case return true, in all other case return false.
if the hourOfDay parameter is less than 0 or greater 23 return false
public class BarkingDog {
public static boolean shouldWakeUp(boolean barking, int hourOfDay) {
if (hourOfDay < 8 || hourOfDay > 22) {
return true;
} else if (hourOfDay < 0 || hourOfDay > 23) {
}
return false;
}
}
Your first statement fails because you are not checking if it’s barking and conditions for less than 0 or greater than 23.
You need to do the following
public static boolean shouldWakeUp(boolean barking, int hourOfDay) {
if (barking) {
if ((hourOfDay > 0 && hourOfDay < 8) || (hoursOfDay > 22 && hoursOfDay <23)) {
return true;
}
}
return false;
}
Based on the comment:
"method call shouldWakeUp(false, -5) returned a value of "true" but "false" was expected
Its not very weird:
if (hourOfDay < 8 || hourOfDay > 22) {
return true;
}
If hourOfDay = -5, it is
hourOfDay < 8
So it will return True. Since your 2nd if statement checks if it is smaller than 0, this might seems weird. But your 2nd if statement is never reached.
If a number is smaller than 0, it is also smaller then 5.
In order to fix this you can do the following:
public static boolean shouldWakeUp(boolean barking, int hourOfDay) {
if (hourOfDay < 0 || hourOfDay > 23) {
return false;
}
return true;
}
Now we check if the value is less than 0 (so -1,-2,-3,etc) or larger than 23 (so 24,25,26,etc) then we return false. In all other cases we return true (this means between 0 and 23)
Edit: ofc you should use the boolean (barking) you provide in the function to check the time and return accordingly as the assignment describes, but I left that out and think you can fix that yourself.
According to the description provided, your method should return false if the time is in invalid range i.e < 0 or > 23.
In your code, when you give invalid time range say -5, it checks against the first condition and the condition is satisfied because, -5 is lesser than 8. So it returns true. Generally what you should do is always put your guard conditions(which returns false) at first.
So, your code should become as this,
[Edited]
public class BarkingDog {
public static boolean shouldWakeUp(boolean barking, int hourOfDay) {
if (hourOfDay < 0 || hourOfDay > 23) {
return false;
} else if (hourOfDay >= 8 && hourOfDay <= 22) {
return false;
}
return barking;
}
}
Things to consider while writing these kinds of conditions
As said before, try to put all guard conditions at first. Hence it is called as guard. Think it of as a security dog infront of a building. It guards the method by checking all of the invalid checks at first returns the control immediately if it doesn’t satisfy.
Ordering of numerical check should be in ascending order. In your case the values(8) you checked against in your first condition is greater than the values(0). So you have to move this condition up a step. Actually this may confuse you in the beginning when you are using conditions with && or || Boolean operators.
These are some of the tips you can have.
I've only just started college, and one of the first things we're learning is Java. I'm currently learning about if statements. For one of my homework assignments, I need to write a program that asks for the user to input a year. Then, the program needs to determine whether that year is a leap year or not.
The question states that if the year is divisible by 4, it is a leap year. Also, if the year is divisible by 100, it should also be divisible by 400 in order to be a leap year.
This is what I've written so far:
System.out.print("Type a year: ");
int year = Integer.parseInt(reader.nextLine());
if (year % 4 == 0 || year % 100 == 0 && year % 400 == 0) {
System.out.print("The year is a leap year.");
} else {
System.out.print("The year is not a leap year.");
}
I'm expecting the program to check if the year is divisible by 4, or if the year is divisible by both 100 and 400.
Right now, when I enter the year 1800, the output says the year is a leap year, but I'm expecting it to say it is not a leap year. I suspect this is because the if statement is true when one of the conditions is true, which is the case because 1800 is divisible by 4. However, I can't seem to find out the right way to do it. Help would be much appreciated.
Your expression is asking "Is year a multiple of four or is it a multiple of 100 and also a multiple of 400?" The second half is entirely redundant because any multiple of both 100 and 400 was already a multiple of 4 in the first place (same with 400 and 100 also) and the result is clearly more inclusive than you intended.
Remember that a series of AND'd conditions will restrict the scenarios that match while ORs will broaden it. So start with finding multiples of four and then refine that a bit by adding in the secondary condition about multiples of 100.
year % 4 == 0 && (year % 100 != 0 || year % 400 == 0) /* right! */
Since A(B+C) is equivalent to AB+AC in Boolean logic you could also expand this and it might read more clearly to you:
(year % 4 == 0 && year % 100 != 0) || (year % 4 == 0 year % 400 == 0) /* expanded */
The parentheses aren't really necessary but I left them for clarity.
Another perspective that might help you think about this is reversing the condition to find the years that aren't leap years. It's very similar in structure to the one you attempted so I think that studying it might give you some insight where your thought process went wrong:
year % != 0 || (year % 100 == 0 && year % 400 != 0) /* NON-leap years */
Finally, one last thing to point out is that it only takes either side of an OR to be true for the whole expression to be true. Looking back at your original logic, once the program has determined that year % 4 == 0 is true the rest of it is extra work that doesn't need to be performed. The program will actually skip those steps and this concept is called short-circuiting.
Another way to word the leap year criteria is this: if the year is divisible by 4 but not by 100, or it is divisible by 400, it is a leap year.
It's the "but not by 100" part that is not expressed in your code.
Example 1 (your fixed code):
System.out.print("Type a year: ");
int year = Integer.parseInt(reader.nextLine());
if (year % 100 == 0 && year % 400 == 0) || (year % 100 != 0 && year % 4 == 0) {
System.out.print("The year is a leap year.");
} else {
System.out.print("The year is not a leap year.");
}
Example 2 (other if for better understand)
System.out.print("Type a year: ");
int year = Integer.parseInt(reader.nextLine());
boolean isLeap = false;
if(year % 100 == 0){
if(year % 400 == 0)
isLeap = true;
} else if (year % 4 == 0){
isLeap = true;
}
System.out.print(isLeap ? "The year is a leap year." : "The year is not a leap year.");
Since any number divisible by 400 or 100 would, obviously, be divisible by 4. We would need to add additional check to make sure the year is a leap year
class Scratch {
public static void main(String[] args) {
for (int i = 1800; i <= 2000; i++) {
if (i % 4 == 0) {
if ((i % 100 == 0 && i % 400 == 0) || (i % 100 != 0)) {
System.out.println(i + ": A leap Year");
} else {
System.out.println(i + ": Not a leap year");
}
} else {
System.out.println(i + ": Not a leap year");
}
}
}
}
Ok so i was looking at someones code for a leap year checker i was wondering why did he/she put ==0 right after year % 4. And also why is modulo(%) used here.. If you use a caculator to find a leap year you would need to use division(/) for a example 2000 / 4 = 500 so it will make 2000 a leap year..
import java.util.Scanner;
public class LeapChecker {
public void Check(){
Scanner input = new Scanner(System.in);
System.out.println("Type a year: ");
int year = input.nextInt();
if (year % 4 ==0 && (year % 100 !=0)){
System.out.println("The year is a leap year.");
}else if (year % 4 ==0 && (year % 100 ==0) && (year % 400 ==0) ){
System.out.println("The year is a leap year.");
}
else {
System.out.println("The year is not a leap year.");
}
}
public static void main(String[] args) {
LeapChecker leap = new LeapChecker();
leap.Check();
}
}
The result of year % 4 is an int.
The && operator (and ||) is defined only for boolean operands, or operands which can be automatically converted to boolean (which means Boolean can be used too).
From the language spec:
Each operand of the conditional-and operator must be of type boolean or Boolean, or a compile-time error occurs.
There is no implicit conversion from int to boolean (unlike other languages such as C, C++, Python etc). This is a good thing: it forces you to be explicit about conversions.
As such, you have to do the int to boolean conversion yourself - for example, using a relational operator like ==, >=, < etc, or by passing the int to a method which returns a boolean.
Simply becuase year % 4 evaluates to 0 if year is evenly dividable by 4 (year 2012, 2016, 2020, ...)
9 % 4 equals 1 since there will be a remaineder of 1 after the division of integers. 10 % 4 equals 2, 11 % 4 equals 3, 12 % 4 equals 0
when you use calculator for division by 4, you know if you get a integer answer, then the year is divisible by 4, similarly in programming languages, modulo operator is used to get the remainder after division, if the remainder is zero (remainder == 0), then the number is divisible by 4.
And, && operator is one which checks all the CONDITIONS surrounding it are true, but yes conditions. It must be surrounded by conditions or technically boolean (true/false) values or literals. And values returned by modulo i.e. 0 or 1 or 2 or 3 (in this case) are not boolean values.
year % 4 ==0 this will return a boolean value and year % 4 will return an int value. For the if condition you need to put a boolean expression.
And year % 4 will give you the remainder after you divide the year. So here you are checking if it's equal to 0. In programming its the way to check if that number is divisible by 4
I'm trying to create a class that accepts user input for a month then outputs the number of days in said month. Whenever I test my class it doesn't give me an output for the number of days but instead just multiplies the month number by 10. Why is this happening and what can I do to fix it?
Here's my code
import java.util.Scanner;
public class Appointment
{
public static void main(String[] args)
{
Scanner kin = new Scanner(System.in);
System.out.print("Enter a number that corresponds to a month: ");
int month = kin.nextInt();
System.out.print(month);
int Days = 0;
System.out.print(Days);
if ( month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12)
{
Days = 31;
}
else if ( month == 4 || month == 6 || month == 9 || month == 11)
{
Days = 30;
}
else if ( month == 2)
{
Days = 28;
}
}
public int getDays()
{
int Days = 0;
return Days;
}
{
} }
You didn't multiply your month by 10; you just printed a 0 immediately after the month. The print method doesn't place anything after what you want to print, not even a newline.
Enter a number that corresponds to a month: 2
20
^^
| \
| --- The `0` is from `Days`
------ The `2` is from `month`
Output a space or some other verbiage, or use println to output a newline after your output, to visually distinguish the two variables' output.
Also, print Days after you get it assigned properly, after all those if statements, so it's not 0 when it's printed.
Your code is fine, but you should use
System.out.println() instead of
System.out.print()
The problem is that you are printing first your month and then, inmediately after the number 0 (variable days) in the SAME Line.
Suggestion for next time, use a debugger :)
You just print out month and then 0 without space. Also in your code your method getDays() never called. It full of mistakes.