Formatting a double to minutes and seconds - java

I'm trying to let the user enter the length of a song except they can enter the length as 5.76 for example. Is there a way I can format that 6.16?
This is how they enter the duration if it makes any difference:
System.out.println("Please enter the length of the song");
double length = sc.nextDouble();

The code below will split the entered time into minutes and seconds, and then operate on the seconds entry to calculate the total number of minutes and seconds are represented by that number.
EDIT Modified the code so that trailing zeroes are not truncated.
System.out.println("Please enter the length of the song");
String length = sc.next("\\d+\\.\\d{2,}");
String[] split = ("" + length).split("\\.");
double minutes = Double.parseDouble(split[0]);
double seconds = (Double.parseDouble(split[1]));
seconds = (Math.floor(seconds / 60)) + ((seconds % 60) / 100);
System.out.println(minutes + seconds);

Get the decimal value and check if its greater than 0.6. You can then subtract it from 0.6 and add that difference and 1 to the floor of the orignal number.
double dec = length - Math.floor(length);
if(dec > 0.6){
double diff = dec - 0.6;
length = length + 1 - dec + diff;
}
However, this might cause a lot of decimals due to the way double is stored in Java. You could get around this, but you should really use a different value to store hours and minutes than a double. You could use an integer for each, and you could initially scan in the input as a String and then process it.

With the following code, you can convert to minutes and seconds, then output that however you want, including put it back into a double (as shown).
int minutes = Math.floor(length);
length -= minutes;
length = Math.floor(length * 100.0);
if (length > 59) {
minutes++;
length -= 60;
}
int seconds = Math.floor(length);
length = ((double) minutes) + ((double) seconds) / 100.0;

Related

Is there a way to represent variables as int instead of double to calculate correct percentage? [duplicate]

This question already has answers here:
How to round a number to n decimal places in Java
(39 answers)
Closed 6 years ago.
I am doing exercise 2.3 on page 23 of Think Java (http://www.greenteapress.com/thinkapjava/thinkapjava.pdf).
The program converts an arbitrary time stored in variables to seconds, then calculates the amount of seconds remaining in the day, then how much of the day has elapsed in percentage.
Here's the working program:
public class Time {
public static void main(String[] args) {
double hour = 21.0; //Represents 9 PM
double minute = 5.0; //Represents 9:05 PM
double second = 33.0; //Represents 9:05:33 PM
final double SEC_IN_MIN = 60.0; //Made final because the amount of seconds in a minute does not change
final double SEC_IN_HOUR = 3600.0; //Made final for the same reason above.
final double SEC_SINCE_MN = (SEC_IN_HOUR * hour) + (SEC_IN_MIN * minute) + second; //Calculates the seconds since midnight, or 00:00
final double SEC_IN_DAY = 24.0 * SEC_IN_HOUR; //Calculates the amount of seconds in a day; 24 stands for the hours in a day
System.out.printf("The number of seconds since midnight is: %.0f\n", SEC_SINCE_MN);
System.out.printf("The number of seconds remaining in the day is: %.0f\n", SEC_IN_DAY - SEC_SINCE_MN);
System.out.printf("The percentage of the day that has passed is: %.0f%%", (100 * SEC_SINCE_MN) / SEC_IN_DAY); // Escape percent sign is %% 100 * to remove decimal value
}
}
I know there is a better way with more advanced code but this is what the assignment required based on what we have learned so far. However, I am not sure double is the best way to represent the variables as I have to use a format specifier to trim the decimal. I asked my professor about it and he said I could change all the variables to int and change the computation in the last print statement to:
System.out.printf("The percentage of the day that has passed is: %d%%", (100 * SEC_SINCE_MN) * 1.0 / SEC_IN_DAY);
This does not work because I get a d != java.lang.Double error for the last print statement. If I change the 1.0 to 1, I get no errors put the last output is incorrect.
It says 87% instead of 88% which is the correct output because the decimal value for the last print statement output is 0.08788.
I think it's my computation that needs to be changed for it to work with int.
Any ideas on how to edit the program for int instead of double?
EDIT 1: Code that doesn't work as per my professor's suggestions (returns java.lang.double error for last print statement)
public class Time {
public static void main(String[] args) {
int hour = 21; //Represents 9 PM
int minute = 5; //Represents 9:05 PM
int second = 33; //Represents 9:05:33 PM
final int SEC_IN_MIN = 60; //Made final because the amount of seconds in a minute does not change
final int SEC_IN_HOUR = 3600; //Made final for the same reason above.
final int SEC_SINCE_MN = (SEC_IN_HOUR * hour) + (SEC_IN_MIN * minute) + second; //Calculates the seconds since midnight, or 00:00
final int SEC_IN_DAY = 24 * SEC_IN_HOUR; //Calculates the amount of seconds in a day; 24 stands for the hours in a day
System.out.printf("The number of seconds since midnight is: %d\n", SEC_SINCE_MN);
System.out.printf("The number of seconds remaining in the day is: %d\n", SEC_IN_DAY - SEC_SINCE_MN);
System.out.printf("The percentage of the day that has passed is: %d%%", (100 * SEC_SINCE_MN) * 1.0 / SEC_IN_DAY); // Escape percent sign is %%. 100 * to remove decimal value
}
}
EDIT 2: Code that works but doesn't give the correct output of 88% for the last print statement
public class Time {
public static void main(String[] args) {
int hour = 21; //Represents 9 PM
int minute = 5; //Represents 9:05 PM
int second = 33; //Represents 9:05:33 PM
final int SEC_IN_MIN = 60; //Made final because the amount of seconds in a minute does not change
final int SEC_IN_HOUR = 3600; //Made final for the same reason above.
final int SEC_SINCE_MN = (SEC_IN_HOUR * hour) + (SEC_IN_MIN * minute) + second; //Calculates the seconds since midnight, or 00:00
final int SEC_IN_DAY = 24 * SEC_IN_HOUR; //Calculates the amount of seconds in a day; 24 stands for the hours in a day
System.out.printf("The number of seconds since midnight is: %d\n", SEC_SINCE_MN);
System.out.printf("The number of seconds remaining in the day is: %d\n", SEC_IN_DAY - SEC_SINCE_MN);
System.out.printf("The percentage of the day that has passed is: %d%%", (100 * SEC_SINCE_MN) / SEC_IN_DAY); // Escape percent sign is %%. 100 * to remove decimal value
}
}
EDIT 3: This is not a dupe question. My question was how to convert the variables to int from doubles, so the percentage was calculated correctly in the last statement. I was not asking about rounding although it did play a part in the question/answer.
The int throws what's after the period. You may want to duplicate in 10 more. Get the first numeral to check if it greater than 5 add one to your percent.
Sorry for not writing code.
I'm on iOS now and my java rusty...
Good luck
(100 * SEC_SINCE_MN) / SEC_IN_DAY
is multiplying the integer SEC_SINCE_MN by the integer 100, and then divides it by the integer SEC_IN_DAY. So that's an integer division. It just truncates the decimal part of the result.
What you want is to compute the accurate percentage, with the decimals, and then round the result. So you need a floating point division:
(100.0 * SEC_SINCE_MN) / SEC_IN_DAY
That will produce a double value (87.88541666666667), that you then need to round:
Math.round((100.0 * SEC_SINCE_MN) / SEC_IN_DAY)

Calculate and Display the Percentage of Time Passed

I'm going through ThinkJava Version 6.1.0 (latest) and in Chapter 2 Exercise 2.3, I'm stuck on #5 which asks "Calculate and display the percentage of the day that has passed. You might run into problems when computing percentages with integers, so consider using floating-point."
I've attempted to get the percentage, but I'm not getting the right result.
I've completed the first 4 questions. Here is what I have so far:
public class Date {
public static void main(String[] args) {
int hour = 13, minute = 58, second = 45;
double percentage;
double secondsSinceMidnight = second + (minute * 60) + (hour * 3600);
double secondsRemainingInDay = (60-second) + ((60-1-minute)*60) + (24-1-hour)*3600;
percentage = (secondsSinceMidnight * 100) / 60;
System.out.println("Number of seconds since midnight:");
System.out.println(secondsSinceMidnight);
System.out.println("Number of seconds remaining in the day:");
System.out.println(secondsRemainingInDay);
System.out.println("Percentage of the day past:");
System.out.println(percentage + "%");
}
}
Thank you for your help and support!
Please check the formula for calculating the percentage of the day already past.
percentage = (secondsSinceMidnight * 100) / 60;
Does not seem right to me. It should be something like
percentage = 100 * secondsSinceMidnight / totalSecondsInDay;
totalSecondsInDay can be the sum of secondsRemainingInDay and secondsSinceMidnight
i think your code have problems with type-casting
in line 3 exchange int with double:
double hour = 13, minute = 58, second = 45;
or there is problem with constant numbers , write numbers in this way : 60.0 instead of 60
Here's an example with a hardcoded time. It's in military time obviously so keep that in mind.
public class Time
{
public static void main(String[] args) {
int startHour = 12; //when you start editing program
int startMinute = 00;
int startSecond = 00;
System.out.print("Number of seconds since midnight: ");
startMinute = (startHour * 60 + startMinute );
startSecond = (startMinute * 60 + startSecond);
System.out.print(startSecond);
System.out.println(" seconds");
int secondInADay = 86400; //number of seconds in a day
System.out.print ("Seconds remaining in the day: ");
System.out.println (secondInADay - startSecond);
System.out.print("Percent of the day that has passed: ");
double startSeconds = 43200; //number of seconds that have passed in a day at start of editing program
System.out.println(startSeconds * 100 / 86400);
int endHour = 16; //time when finished editing program
int endMinute = 00;
int endSecond = 00;
System.out.print ("Difference = "); //difference in time from start to finish
endMinute = (endHour * 60 + endMinute );
endSecond = (endMinute * 60 + endSecond);
System.out.print (endSecond - startSecond);
System.out.print (" seconds");
}
}

Converting a float number to years, months, weeks, days

I've been trying to convert a float number to years, months, weeks, days, hours, minutes and seconds but I'm not getting it.
For example, if the user enters 768.96 the total would be 2 years, 1 month, 1 week, 1 day, 23 hours, 0 minutes and 2 seconds.
This is what I have.
import javax.swing.JOptionPane;
public class timePartition {
public static void main(String[] args) {
float totalTime;
float userInput;
int years = 0, months = 0, weeks = 0, days = 0, hours = 0, minutes = 0, seconds = 0;
do{
userInput = Float.parseFloat(JOptionPane.showInputDialog("Enter a positive number to decompose"));
totalTime = userInput;
years = (int) userInput / 365;
userInput = userInput % 10;
months = (int) userInput / 12;
userInput = userInput % 10;
weeks = (int) userInput / 4;
userInput = userInput % 10;
days = (int) userInput / 30;
userInput = userInput % 10;
hours = (int) userInput / 24;
userInput = userInput % 10;
minutes = (int) userInput / 60;
userInput = userInput % 10;
seconds = (int) userInput / 60;
userInput = userInput % 10;
}while (userInput >=1);
System.out.print("The number " +totalTime+ " is " +years+ " years, " +months+ " months, " +weeks+ " weeks, " +days+ " days, " +hours+ " hours, " +minutes+ " minutes, " +seconds+ " seconds.");
}
I don't think you can use modulo 10 to reduce the input after you pull out each of the denominations. Also, you don't need a while loop at all for this.
You have to do something like
years = (int) (userInput / 365);
userInput = userInput - years*365;
and so on. Also, since the input is in days, you have to keep thinking in days when you divide out, so dividing by 12 to get the number of months doesn't make sense. You would instead divide by 30, 31 or 28. Similarly for hours, you would have to multiply the remaining fraction of days by 24, and then take the fractional part of the hours and decompose it similarly into minutes and seconds.
Ok, several things here:
just to make sure you're aware: date/time arithmetic is not as simple as it may seem. Several fields are not uniform in duration, including years (due to leap years in some years but not others), months (28-31 days depending on the month), and even minutes (due to rare but strictly necessary leap seconds). This means that technically you can't properly decompose a total duration count (e.g. "x days") into duration fields, and vice-versa (at least not without some "anchoring" date/time point).
if you want to make incorrect assumptions like "all years have exactly 365 days" and "all months have exactly 30 days" and "all minutes have exactly 60 seconds" then this can be done.
I'm not sure whether you wanted your program to take and decompose a single value, in which case the loop is not necessary, or multiple values, in which case the final print statement should be inside the loop. I've assumed the latter.
based on your example input and the start of your decomposition code, it appears that you want the integral part of the input float value to represent a number of days, with the fractional part representing a time value as a fraction of one day. Your decomposition code is incorrect according to this interpretation; you first must separate the ipart and fpart to decompose independently, and in each step of the decomposition, you must take the remainder on the previous field duration size (e.g. 7 days for a week, 3600 seconds for an hour), rather than a fixed value of 10 (not sure where that came from...) to prepare for the next step of the decomposition. This can be done with the mod-assign operator %=.
Here's working code:
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class TimePartition {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while (true) {
System.out.println("Enter a positive number to decompose");
String input = br.readLine();
if (input.equals("")) break;
float inputAsFloat = Float.parseFloat(input);
if (inputAsFloat == 0.0) break;
// the input is an integral day count, with a possible fractional part representing time as a fraction of one day
int totalDays = (int)inputAsFloat;
int totalSeconds = (int)((inputAsFloat-totalDays)*60.0*60.0*24.0);
// decompose totalDays into date fields
int years = 0;
int months = 0;
int weeks = 0;
int days = 0;
// ignores leap years
years = (int)totalDays/365;
totalDays %= 365;
// assumes all months have 30 days
months = (int)totalDays/30;
totalDays %= 30;
weeks = (int)totalDays/7;
totalDays %= 7;
days = (int)totalDays;
// decompose totalSeconds into time fields
int hours = 0;
int minutes = 0;
int seconds = 0;
hours = (int)totalSeconds/3600;
totalSeconds %= 3600;
// ignores leap seconds
minutes = (int)totalSeconds/60;
totalSeconds %= 60;
seconds = (int)totalSeconds;
System.out.println("The number "+inputAsFloat+" is "+years+" years, "+months+" months, "+weeks+" weeks, "+days+" days, "+hours+" hours, "+minutes+" minutes, "+seconds+" seconds.");
} // end while
} // end main()
} // end class TimePartition
Demo:
bash> ls
TimePartition.java
bash> javac TimePartition.java
bash> ls
TimePartition.class* TimePartition.java
bash> CLASSPATH=. java TimePartition
Enter a positive number to decompose
768.96
The number 768.96 is 2 years, 1 months, 1 weeks, 1 days, 23 hours, 2 minutes, 25 seconds.
I suppose the input is in day.
There are few strange thing in your code :
the while loop is not necessary
(int) userInput will cast userInput in int before the division, not really important here, but be careful ;)
userInput % 10 everywhere
divide by 12 to get the number of month, by 4 to get the number of weeks, and so on
Here is a skeleton of the solution:
float userInput /* = ... */ ;
int years = (int)(userInput/365) ;
userInput = userInput - years*365 ; // or userInput%365 ;
int month = (int)(userInput/30);
userInput = userInput - month*30 ; // or userInput%30 ;
int day = (int) userInput ;
userInput = userInput - day ;
userInput = userInput * 24 ; //transform in hours
int hours = (int)hours ;
userInput = userInput - hours ;
userInput = userInput * 60 ; // transform in minute
int minutes = (int)userInput ;
userInput = userInput - minutes ;
userInput = userInput * 60 ; // transform in second
int seconds = (int) userInput ;

Java split two integers from a string into double (converting time)

Part of an assignment I have for a beginning Java class is to take a time entered in as a string and convert it (while rounding to the nearest quarter hour) to a double and store it in an array. The part I am having difficult with is what to do with the two integers I receive from the split method of the String class. How do I make the two integers into one double to use in the array? (So it would be like hours.minutes, or 5.25)
Here is a snippet of code from a program I am working on:
public static double convertClockOutTimes(String clockOut){
double convertedTimeOut = 0;
String time = clockOut;
int hours;
int minutes;
String[]splitFields;
splitFields = time.split(":");
hours = Integer.parseInt(splitFields[0]);
minutes = Integer.parseInt(splitFields[1]);
if (minutes <= 7)
{
minutes = 0;
}
else if (minutes >= 8 || minutes <= 22)
{
minutes = 15;
}
else if (minutes >= 23 || minutes <= 37)
{
minutes = 30;
}
else if (minutes >= 31 || minutes <= 53)
{
minutes = 45;
}
else
minutes = 0;
hours = hours + 1;
convertedTimeOut = //This is where I don't know what to do!!
return convertedTimeOut;
}
I think the trick is to use a bit of math here. You could always do the following:
double convertedTimeOut = Math.round(minutes / 15.0) * 0.25 + hours;
then you don't need the if-else tree to figure out the nearest quarter hour.
There are 15 minutes in a quarter hour, and a quarter hour is 0.25 hours. Using the formula above, you are dividing the minutes into how many quarters of an hour you've got (0-4), which you then multiply by how many hours are in a quarter hour. Then add that to the hours you've got.
Math.round just does the rounding for you.
I'm guessing what's giving you the most trouble is how to deal with the minutes. Try this:
double minutesAsDecimal = 0.01 * minutes;
So if the number of minutes was 24, you would end up with 0.24. I bet you'll know where to go from there.
Just as a side note, your if and else ifs are not doing what you think they are. But since it's homework.. Just take a closer look at your logic there.
Your conditions should be AND not OR:
if(minutes >= 8 && minutes <= 22)
Etc, or better yet, a single statement, simply
minutes = ((minutes + 7) % 15) * 15;
which calculates the rounding using arithmetic rather than logic.

Convert simple time format to Special time format (hhmmt)

I'm trying to convert the time format (hh:mm:ss) to this Special Time Format (hhmmt)?
The Special Time Format (STF) is a 5 digit integer value with the format [hhmmt] where hh are the hours, mm are the minutes and t is the tenth of a minute.
For example, 04:41:05 would convert to 4411.
I'm not sure how to convert the seconds value (05) to a tenth of a minute (1).
Edit:
I've incorporated Adithya's suggestion below to convert seconds to a tenth of a minute, but I'm still stuck.
Here is my current code:
String[] timeInt = time.split(":");
String hours = timeInt[0];
String minutes = timeInt[1];
double seconds = Double.parseDouble(timeInt[2]);
int t = (int) Math.round(seconds/6);
if (t>=10) {
int min = Integer.parseInt(minutes);
// min+=1;
t = 0;
}
String stf="";
stf += hours;
stf += minutes;
stf += String.valueOf(t);
int stf2 = Integer.parseInt(stf);
return stf2;
I'm using a String to store the minutes value but it makes it difficult to increment it since it is a String and not a Integer. But when calculating the "t" (tenth of minute) I have to add 1 to minutes if it exceeds 10. If I were to use parseInt again it will exclude the 0 in front of minutes again.
How can I retain the leading zero and still increment the minutes?
Thanks.
I am guessing, its the value of seconds, compared to the tenth of a minute, which is 6 seconds. So formula for t would be
t= seconds/6 //rounded off to nearest integer
This makes sense as this value is always between 0 and 9, as seconds range from 0 and 59, so its always a single digit
For your example
t = 5/6 = 0.833 = rounded off to 1
Note the 6.0f in the division - this helps you avoid the INT truncation.
string FormatSpecialTime(string time)
{
if (time.Length != 8) throw YourException();
int HH, mm, SS, t;
if (!int.TryParse(time.Substring(0, 2), out HH)) HH = 0;
if (!int.TryParse(time.Substring(0, 2), out mm)) mm = 0;
if (!int.TryParse(time.Substring(0, 2), out SS)) SS = 0;
t = (int) Math.Round(SS / 6.0f);
if (t >= 10)
{
mm++;
t = 0;
}
if (mm >= 60)
{
HH += mm / 60;
mm = mm % 60;
}
return HH.ToString() + (mm > 10 ? mm.ToString() : #"0" + mm) + t;
}

Categories

Resources