I'm attempting to take the current system time,
long now = System.currentTimeMillis();
find out how far light has traveled since 1970 (in km),
double km = (now / 1000.0) * 299792.458;
and print the value.
System.out.printf("Since the unix Epoch, light has traveled...\n%f km", km);
But when I run the code, I'm only getting the answer down to two decimals.
435963358497001.750000 km
Is there a reason for this? Printing the value using
System.out.println(km);
gives me
4.3596335849700175E14
Seeing the E there makes sense why it cuts off. Is there a way I could get the value to 3 or more decimal places?
You are exceeding the precision of a double (15 to 17 decimal digits), so the result is rounded.
Try using BigDecimal instead:
long now = 1454217232166L; // Sun Jan 31 00:13:52 EST 2016
BigDecimal km = BigDecimal.valueOf(now).multiply(BigDecimal.valueOf(299.792458));
System.out.println(km); // prints: 435963358497001.804028
Just format it to three places, try this.
System.out.printf("Since the unix Epoch, light has traveled...\n%.3f km", km);
Related
Making a application for ordering tickets. For the total, I added the subtotal, hst, and service fees together, and decimal formatted the sum for the total. If the total is x.85, it rounds down to x.8 but I want x.9
Is there a way to remove the even-odd rule for rounding 5 and round up?
I have tried BigDecimal but it doesn't seem to work for me.
DecimalFormat df = new DecimalFormat("$#,###.00");
grandTotal = subTotal + hst + serviceFees;
System.out.printf("%-40s%11s\n", "TOTAL:", df.format(grandTotal));
I expect the output to round up when there is a 5 to round, but it just rounds based on the even-odd rule.
You need only 1 fraction digit.
You current code is rounding correctly, just too many fraction digits.
The rounding mode you are asking for is called HALF UP, which is a default for DecimalFormat and the only possible rounding mode for printf().
(You can also use format $#,###.# if you don't want to display zeros as fraction.)
Therefore you can use your decimal format just fine or even System.out.printf() but limit number of fraction digits to 1:
DecimalFormat df = new DecimalFormat("$#,###.0"); //set MIN and MAX fraction digits to 1
df.setRoundingMode(RoundingMode.HALF_UP); //default but showing usage if needed
System.out.println(df.format(123454.84d));
System.out.println(df.format(123454.85d));
System.out.printf("$%,.1f", 123454.85d); //HALF UP rounding the only option
prints:
$123,454.8
$123,454.9
$123,454.9
You are using floating point (double), which is just an approximation of real values.
Especially with a list and a total, you will always have trouble to get everything right.
You have no control, whether the total is 2.35 (actually never) or 2.349999998, the latter which would round down.
Use BigDecimal with String constructors: new BigDecimal("1.20"), having a fraction of 2 decimals.
Mind you must use add/multiply i.o. +/*.
Guys i just switched the double data type into a float type and it worked ayyyyy
!!!!!!!
Will these statements execute with exactly the same results across different platforms?
currentTime = System . nanoTime ( ) * 0.000000001f ; // 01
currentTime = System . nanoTime ( ) / 1000000000f ; // 02
The concern is loss of precision using a small floating point value.
Just leave it as a long. No loss of precision and perfect Determinism across the board.
I am using Ruby to generate a 64 bit timestamp similar to Java. I went through Class:Time and it says time could use 63 bit integer. I thought I could use:
Time.now.to_f * 1000
but I am worried about losing precision due to the floating point conversion. Can I simply get the 64 bit timestamp (millis since epoch) as in Java in ruby, as precise as possible?
Calendar.getInstance().getTimeInMillis();
I need to use the timestamp as unique ID in a database, so I would like to keep time-related collisions from minimum to non-existent.
I've added comments suggesting this really isn't what you should be doing anyway, but I really don't think you need to worry about losing precision in any meaningful way. The Ruby documentation states that the value is stored down to the nanosecond. Converting it to a floating point number may lose the last few digits, but it's not going to be significant at the millisecond level - you really don't care if the value round up or down a bit, after all... you're already relying on only creating a single entry per millisecond.
An alternative approach would be to use to_i and nsec: multiply the result of to_i by 1000, divide the result of nsec by 1000000, and add the two together. That will get you the number of milliseconds using only integer arithmetic.
The time is signed long in Java so it is 63-bit also.
So you are worried that in this year you will get an overflow? Personally, I don't think anyone will be using Java by then. In fact it's likely we will be extinct/evolved by then as well.
System.out.println("Overflow at " + new Date(Long.MAX_VALUE));
prints
Overflow at Sun Aug 17 08:12:55 CET 292278994
Note: 292 million years ago was before the dinosaurs ruled the earth.
If you are concerned about the loss of accuracy of converting a nano-second time stamp to double you can calculate what that error is
long now = System.currentTimeMillis() * 1000000L;
double error_f = Math.ulp((float) now);
double error = Math.ulp((double) now);
System.out.println("The error for a nano-second timestamp using a double "
+ now + " is " + error + " and float is " + error_f);
prints
The error for a nano-second timestamp using a double 1378970569656000000 is 256.0 and float is 1.37438953472E11
This means the error for converting to double is up to half of this which is 128 ns, for converting to float, the error is also half the ulp, which is 68 seconds, which is quite high.
how to keep only 3 value after point in BigDecimal ?
i found a solution but it requirt a RoundingMode
BigDecimal d = BigDecimal.valueOf(0.5649);
System.out.println(d.remainder(BigDecimal.ONE));
System.out.println(d.remainder(BigDecimal.ONE).divide(BigDecimal.valueOf(1), 3, RoundingMode.CEILING));
i want to keep a number exact without rounding.
Just use setScale and RoundingMode.DOWN
Rounding mode to round towards zero. Never increments the digit prior
to a discarded fraction (i.e., truncates).
for example
BigDecimal.valueOf(0.5649).setScale(3, RoundingMode.DOWN)
BigDecimal isn't intended to be used with such limitations. Only ever wanting 3 decimals is a strange requirement. Maybe you only want to present 3 decimals to the users?
If so I suggest using: java.text.DecimalFormat
If you really want to make sure that you never do calculations with higher precission than 3 decimals I suggest making your own reprensentation/class. Internally you hold the value as a long (or appropriate class/primitive) but at a value 1000 times the actual value. All calculations are done with the internal reprensentation and when asked for a value, divide the internal value with 1000.0d and convert to double (or appropriate) and return.
I would use double for this.
double d = 0.5649;
d = (long) (d * 1000) / 1000.0; // round down.
System.out.println(d);
prints
0.564
or
d = (long) (d * 1000 + 0.5) / 1000.0; // round half up.
I have number displayed in EditText that can go up to 20 character + 4 decimal before it's too long. I would like to have number that are longer than that displayed with de exposant at the end so it's not truncated.
ex: 123456789 will show as is
123456789123456789123456 is too long and will be displayed as 1.123456789E8 (just an example !)
I have tested this:
DecimalFormat df = new DecimalFormat("#.####");
df.setMaximumIntegerDigits(20);
But after 20char, the numbers are just not displayed correctly. ex: 123456789123456789123456 became 56789123456789123456 (trunked 4 first digit.)
Thank you !
The Decimal Formater java doc descibe how to handle the Exponent.
Scientific Notation
Numbers in scientific notation are
expressed as the product of a mantissa
and a power of ten, for example, 1234
can be expressed as 1.234 x 10^3. The
mantissa is often in the range 1.0 <=
x < 10.0, but it need not be.
DecimalFormat can be instructed to
format and parse scientific notation
only via a pattern; there is currently
no factory method that creates a
scientific notation format. In a
pattern, the exponent character
immediately followed by one or more
digit characters indicates scientific
notation. Example: "0.###E0" formats
the number 1234 as "1.234E3".
...
The more difficult part is how to switch betwenn normal and Scientific Notation.
I have done this by embedding two decimal formater in an choide formatter within an Messageformater:
MessageFormat format = new MessageFormat(
"{0,choice,0#{0,number,'#,##0.####'}|99999<{0,number,'000000.####E0'}}",
Locale.ENGLISH);
(This excample is with only 6 decimal places, but you can change it.)
The usage of an message format is a bit different to an decimal formater, because the format metthod expect an array of objects.
System.out.println(format.format(new Object[] { 123 }));
What it prints for (1, 12, 123, ...) is:
1
1.1
12
123
1,234
12,345
123456E0
123456.7E1
123456.78E2
123456.789E3
123456.789E4
123456.789E5
123456.789E6
You need to tune the pattern a bit that it matches your 20 diget requirement, but the way should be clear.
Even if I have showed that it worked, I would recommend to implement your own Formater which uses 2 decimal formater and an if condition.
E is used to Format the number in Exponential Notation. Is that what you're looking for?
new DecimalFormat("####E0")
I'm not sure what an exposant is.
Sorry, Exposant is Exponent in french !
This work, but I would like to have exponential format only when number is longer than 20 characters. And if it's 20 or less character, I want to have the 4 decimals if there's any...
Thanks Ralph ! Exactly what I was loking for !
Here what I have done:
MessageFormat df = new MessageFormat("{0,choice,0#{0,number,'#.####'}|9999999999999999999<{0,number,'#.######E0'}}",
Locale.ENGLISH);
EditText2.setText(String.valueOf(df.format(new Object[] { Float.valueOf(EditText1.getText().toString()) * 1024})));