Java - Converting hours(in double) to minutes(integer) and vice versa - java

I need the correct formula that will convert hours to minutes and vice versa.
I have written a code, but it doesn't seem to work as expected.
For eg:
If I have hours=8.16, then minutes should be 490, but I'm getting the result as 489.
import java.io.*;
class DoubleToInt {
public static void main(String[] args) throws IOException{
BufferedReader buff =
new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter the double hours:");
String d = buff.readLine();
double hours = Double.parseDouble(d);
int min = (int) ((double)hours * 60);
System.out.println("Minutes:=" + min);
}
}

That's because casting to int truncates the fractional part - it doesn't round it:
8.16 * 60 = 489.6
When cast to int, it becomes 489.
Consider using Math.round() for your calculations:
int min = (int) Math.round(hours * 60);
Note: double has limited accuracy and suffers from "small remainder error" issues, but using Math.round() will solve that problem nicely without having the hassle of dealing with BigDecimal (we aren't calculating inter-planetary rocket trajectories here).
FYI, to convert minutes to hours, use this:
double hours = min / 60d; // Note the "d"
You need the "d" after 60 to make 60 a double, otherwise it's an int and your result would therefore be an int too, making hours a whole number double. By making it a double, you make Java up-cast min to a double for the calculation, which is what you want.

8.16 X 60 comes out to be 489.6 and if you convert this value to int, you will get 489
int a = (int)489.6;
System.out.println("Minutes:=" + a);

Related

Java converting seconds to year day hours minute seconds

I have a problem regarding really big numbers in Java.
I'm currently trying to convert a double consisting of a large number of seconds into years, days, hours, minutes and the seconds that are left.
My code looks like this: `
import java.util.Scanner;
public class timer {
public static void main(String[] args){
double sum = 1.1078087563769418E16;
double sec=0;
double min=0;
double hou=0;
double da=0;
double yea=0;
yea=sum/31536000;
int year = (int) yea;
sum=sum-year*31536000;
da=sum/86400;
int day = (int) da;
sum=sum-day*86400;
hou=sum/3600;
int hour = (int) hou;
sum=sum-hour*3600;
min=sum/60;
int minute = (int) min;
sum=sum-minute*60;
sec=sum;
int second = (int) sec;
sum=sum-second*60;
System.out.println(year+" "+day+" "+hour+" "+minute+" "+second);
}
}
`
When the double "sum" is as large as it is, the output gets weird. For example, the double "day" becomes larger than 365, which should be impossible.
Any solutions?
You are facing with a very common problem that most developers should know about: Integer overflow.
Your year variable is an int, the constant for second->year conversion is constant int, so int*int is... int. Except if your year is larger than approx 68, the result cannot fit into an int. Hence - overflow and silly results.
You have a couple of options available to you:
Do your timestamp arithmetic in longs. Really, that's the industry standard anyway.
If you insist on precision of over microseconds (or nano if you're concerned with last century only) - BigDecimal or BigInteger are your friends.
Use the TimeUnit class from concurrent package. It doesn't have years, but does have days and does conversion nicely (JodaTime would be even nicer though)
Overflow on the calculation sum=sum-year*31536000;
year and 31536000 are both integers, and their product is ~1E16, which is larger than java's max integer size. Use sum = sum-year*31536000.0 instead.
As a demonstration, add this code after you compute year:
System.out.println(year * 31536000.0); // 1.1078087556672E16
System.out.println(year * 31536000); // 1100687872
You can use java.math.BigDecimal class if you need to represent numbers with great precision.
If you need huge integers you can use java.math.BigInteger.
First use long not double then try this logic
long min = sum / (60) % 60;
long hou = sum / (60 * 60 )% 24;
long da = sum/(60*60*24)%30;
long yea = sum/(60*60*24*30)%365;
If that number is beyond the limit of long then use BigInteger but then this calculation will not work.

Why do I need to add an 'f' to value so my code outputs the right value? [duplicate]

This question already has answers here:
Why does the division of two integers return 0.0 in Java? [duplicate]
(6 answers)
Closed 9 years ago.
The following is my code that works ::
public class AvgSpeed{
public static void main(String[] args){
double kph, km, hours, seconds, minutes, time;
km = (1.6 * 24);
hours = 1;
minutes = 2/3f;
seconds = 35/3600f;
time = hours + minutes + seconds;
kph = km/time;
System.out.println(kph);
}
}
If I remove the f's for minutes and seconds, it keeps printing out 38.4, which is not right. It should be some number close to 22.906
I don't even know the reason why I need to add the f, I did it on a whim. I thought declaring the two variables as a double was enough?
Declaring the variables as doubles doesn't make 2 or 3 a double. The conversion to double only happens after 2/3 is computed in integer arithmetic. To fix this, do the calculation in double arithmetic:
minutes = 2.0/3;
// ^ double
seconds = 35.0/3600;
// ^ double
The trailing f you appended made 3f and 3600f float literals. That's close to what you want, but not as good as doubles.
In Java, 18.45 is a double data type which holds 64-bit. float data type can hold up to 32-bit only. Adding the extra f makes it a float (float literal).
See http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html for more detail
double minutes;
minutes = 2/3;
This code takes two integers, divides them, converts the result to a double and stores it in minutes. In that order. To get the result you want you need to convert to doubles before the division happens. You managed to do this by adding f (use d for double, btw). You could also do it with minutes = 2.0/3.0;

Java Variable conversion

I need to write a small Java program that deals with calculations involving money. Therefore it needs to have accuracy. (Eg: No float/double variables, only long).
Unfortunately, the original value I need to use is imported through a method which can only read variables as "double".
Now, I tried casting it to a long using a method similar to:
double importedValue = x;
double importedValueConverted = (long) x;
However, when I try dividing importedValueConverted by another "long" variable I get:
required: long
found: double
error: possible loss of precision
Why is that?
double importedValue = x;
double importedValueConverted = (long) x;
Note that both of these variables are declared as 'double'. This results in your error (paraphrasing): (the operation you're doing requires a) long (but when it tried it found a) double.
You want:
double importedValue = x;
long importedValueConverted = (long) x;
Forget all the casting business. If you are working with financial calculations, you can directly use BigDecimal to wrap the doubles returned by your so called method and use an appropriate rounding mechanism provided by BigDecimal that suits your needs.
Update:
This post raised an additional question which I don't think was ever answered-- why use int, or better yet, long or BigDecimal for currency calculations. This is answered here:
Why not to use double or float to represent currency (or where any exact calculations are needed)?
Because floats and doubles cannot accurately represent most base 10
real numbers.
And even when using BigDecimal, one must use the String constructor and not the float one.
This all said, your best bet is to:
Convert all values to cents and store as a long (multiply each dollar amount by 100)
Do the operations in cents
Convert back to dollars by dividing by 100 at the end
This will retain the accuracy desired. Obviously this solution has USD in mind, any conversions to foreign currencies would need appropriate consideration.
Rather than casting, consider rounding to the nearest long value:
double d = 1234.56;
long x = Math.round(d);
Tho really I ask why you'd want to go from a double to a long, as this is going to lose you the precision of the decimal values.
If you want to keep some precision (up to 3 digits, say), and you can absolutely only work with long to do so, you can multiply both doubles by 1,000, then scale all later operations by the same factor, and then scale them all back at the end, like so:
double starting = 1234.5678;
double worker = starting * 1000;
long roundedWorker = Math.round(worker);
// do other computations here...
// due to earlier scaling, adding 1000 is equivalent to adding 1 to the original
long longResult = roundedWorker + 1000;
double threeDigitPreciseResult = longResult / 1000d;
System.out.println("Adding 1 to original number as a long: " + threeDigitPreciseResult);
Update
After getting a better explanation of the problem, it sounds like what you're looking for is the functionality provided by DecimalFormat. Below is a method roundToTwoDecimals() which uses it, along with a test case demonstrating it:
import java.text.DecimalFormat;
import org.junit.Test;
public class ExampleTest {
#Test
public void test() {
double num1 = 29334.32942032432;
double num2 = 438.95940;
double result = num1 / num2;
System.out.println("Before rounding: " + result);
double rounded = roundToTwoDecimals(result);
System.out.println("After rounding: " + rounded);
}
public double roundToTwoDecimals(double d) {
DecimalFormat twoDForm = new DecimalFormat("#.##");
return Double.valueOf(twoDForm.format(d));
}
}
Which prints out:
Before rounding: 66.82697629968585
After rounding: 66.83
You're casting x to a long than trying to assign it to a double.
That doesn't make sense.
If you want a long, you should use a long.
long longValue = (long) 4.64;
If you wanna cast double to long you do below.
double importedValue = 8.0;
long importedValueConverted = (long) 8.0;
System.out.println(importedValueConverted/(long)8);
OUTPUT: 1
double importedValue = x;
double importedValueConverted = (long) x;
you were trying to cast a double to long and reassign the casted value to a double. you should assign it to long.
Why not look at BigDecimal. It works well when I have used it. Be careful using the Double ctor though as Double is not that precise (eg it cannot accurately store 0.1). It may be more useful to use the String ctor for BigDecimal

Rounding a double

Hey guys, I am trying to round to 3 decimal places.
I used the following code.
this.hours = Round(hours + (mins / 60), 3);
But it's not working.
Where have I gone wrong?
Thanks
You can use this function:
public static double Round(double number, int decimals)
{
double mod = Math.pow(10.0, decimals);
return Math.round(number * mod ) / mod;
}
First thing is that all your variables are int so the result of your division is also an int, so nothing to Round.
Then take a look to: How to round a number to n decimal places in Java
If mins is an integer, then mins / 60 will result in an integer division, which always results in 0.
Try changing from 60 to 60.0 to make sure that the division is treated as a floating point division.
Example:
int hours = 5;
int mins = 7;
// This gives 5.0
System.out.println(Math.round(1000 * (hours + (mins / 60 ))) / 1000.0);
// While this gives the correct value 5.117. (.0 was added)
System.out.println(Math.round(1000 * (hours + (mins / 60.0))) / 1000.0);
if mins is an integer you have to divide through 60.0 to get a floating number which you can round
try using like follow
this.hours = Round(hours + (((double)mins) / 60), 3);
You can't. Doubles don't have decimal places, because they are binary, not decimal. You can convert it to something that does have decimal places, i.e. a base-ten number, e.g. BigDecimal, and adjust the precision, or you can format it for output with the facilities of java.text, e.g. DecimalFormat, or the appropriate System.out.printf() string.

How to save decimal in java

Having the following code in Java:
double operation = 890 / 1440;
System.out.println(operation);
Result:
0.0
What I want is to save the first 4 decimal digits of this operation (0.6180). Do you know how can I do it?
Initialize your variable with an expression that evaluates to a double rather than an int:
double operation = 890.0 / 1440.0;
Otherwise the expression is done using integer arithmetic (which ends up truncating the result). That truncated result then gets converted to a double.
You can use the double literal d - otherwise your numbers are considered of type int:
double operation = 890d / 1440d;
Then you can use a NumberFormat to specify the number of digits.
For example:
NumberFormat format = new DecimalFormat("#.####");
System.out.println(format.format(operation));
You can also do something like this:
double result = (double) 890 / 1400;
which prints the following:
0.6180555555555556
You can check how to round up the number here
This is done using BigDecimal
import java.math.BigDecimal;
import java.math.RoundingMode;
public class DecimalTest {
/**
* #param args
*/
public static void main(String[] args) {
double operation = 890.0 / 1440.0;
BigDecimal big = new BigDecimal(operation);
big = big.setScale(4, RoundingMode.HALF_UP);
double d2 = big.doubleValue();
System.out.println(String.format("operation : %s", operation));
System.out.println(String.format("scaled : %s", d2));
}
}
Output
operation : 0.6180555555555556
scaled : 0.6181
BigDecimal, although very clumsy to work with, gives some formatting options:
BigDecimal first = new BigDecimal(890);
BigDecimal second = new BigDecimal(1440);
System.out.println(first.divide(second, new MathContext(4, RoundingMode.HALF_EVEN)));
double operation = 890.0 / 1440;
System.out.printf(".4f\n", operation);
If you really want to round to the first 4 fractional digits you can also use integer arithmetic by first multiplying the first number so its digits are shifted the right amount f places to the left:
long fractionalPart = 10000L * 890L / 1440L;
I'm using long here to avoid any overflows in case the temporary result does not fit in 32 bits.

Categories