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.
Related
Sorry im new to java, currently i wanted to code the value to next thousand instead of nearest thousand. But i have no ideas how to do it. I tried Math.round but it's for roundest. Please guide me, any help would be appreciated .
Expected output that i looking for :
example 1) if the place values less than 999, it will direct change to 1000
May i know how can i code the math formula for this ?
You can use Math.ceil for this.
// A quick code example :)
int val = 1400;
val = (int) (Math.ceil(val / 1000.0) * 1000);
You need to write some custom code as follow
int leftdigit=value/1000;
int nextthousand=(leftdigit+1)*1000;
Here Kindly note Math.ceil returns double so you should use it properly as stated below as for integer value it won't work properly and integer division will be performed.
double data = 1100;
data = Math.ceil(data / 1000) * 1000;
System.out.println(data);
OUTPUT
2000.0
Conversion from integers to floats leads to chaos, as for the same bit size, float mantissa length will always be smaller than integer size (IEEE-754 float mantissa is 23 bits vs 31 bits for the integer). Converting a large integer to float back and forth will not give the same integer after the conversion.
So here using Math.ceil() may work for integers or small long ints, but will break for large long values (63 bits).
Better use the following code (only works for value > 0):
int ii = ((i - 1) / 1000 + 1) * 1000;
or for long int version:
long ii = ((i - 1) / 1000 + 1) * 1000;
Does not unnecessarily overflow, keep precision even for large values, and probably way faster!
Addenda
As an example, the following java code:
int largeint = Integer.MAX_VALUE - 63;
float fl = (float)largeint;
int largeint2 = (int)fl;
System.out.println(largeint);
System.out.println(largeint2);
Print:
2147483584
2147483647
String phrase = "4556.44";
Float num = new Float(phrase);
int dollars = (int) Math.floor(num);
System.out.println(""+dollars);
int cent = (int) Math.floor((num - dollars) * 100.0F);
int cent2 = (int) ((num - dollars) * 100.0);
System.out.println(""+cent+":"+cent2);
This is a Number to Word Class Code Phrase, My Problem is when I run this code fragment the output result is 4556.43. But the input value is 4556.44. Please tell me why this is happened and I need the answer for correct this Problem.
For high precision calculations with controlled rounding use BigDecimal instead Float
Floats are less precise than doubles which are less precise than BigDecimal.
When working with programmes that absolutely must be precise (like financial applications) use a BigDecimal.
If this is a small homework and non-critical app you can try out Double to see if it is precise enough for you.
int cent = (int)(num * 100f % 100f);
Float is not a good choice for precision calculations.
int cent = (int) Math.floor((num - dollars) * 100.0F);
above statement in the code doesn't exactly give you precise answers as you would expect.
Try using Double or BigInteger if possible.
Floats and Doubles cannot represent all possible real numbers, since they use a specification that makes up numbers by adding any of the following numbers: 1, 1/2, 1/4, 1/8, 1/16 etc...
If you try out 0.1f+0.1f+0.1f==0.3f you'll get false. So, as other people said, use BigDecimal, it uses a different representation, it's much slower, but it won't incur in these problems.
You can also do the following
String phrase = "4556.44";
long money = Math.round(Double.parseDouble(phrase) * 100);
long dollars = money / 100;
long cents = money % 100;
System.out.printf("%,d dollars and %d cents%n", dollars, cents);
prints
4,556 dollars and 44 cents
I came across this problem, I have a number of type long which represents time (only seconds and miliseconds). I would like to display it for example like this 1,124 ms. I thought that simple division would do the job, so I tried this code
long time = 2;
System.out.println(((float) time) / 1000);
But when the number has only one digit like in the example above, it's giving me 0,0020. So is there a way how to correct my formula or I have to manually cut the last zero?
Just use a formatting statement that makes it 3 decimal places
String.format("%.3f", floatValue);
If you need to find out more about number formatting check out this link
this will do the task
long time = 2;
float num = ((float) time) / 1000;
DecimalFormat df = new DecimalFormat("#.###");
String str = df.format(num);
System.out.println(str);
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);
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.