How do you reduce a java double to n significant digits? - java

I am looking to print small digits (doubles) for the purpose of printing the errors in using the Newton & Secant methods.
One of my errors is 5.433306166802499E-5
I'd like to print 5.4333E-5
I thought of using BigDecimal but I am not familiar with this class.

I am looking to print small digits (doubles)
System.out.printf("%.4e", 5.433306166802499E-5);
Result: 5.4333e-05
Note: it doesn't reduce the precision of your original value, it just prints it with a lower precision.

double d = 5.433306166802499E-5;
BigDecimal dc = new BigDecimal(d);
dc = dc .round(new MathContext(3)); // desired significant digits
double rounded = dc .doubleValue();

You can indeed use BigDecimal, it would then look as follows:
BigDecimal d = BigDecimal.valueOf(val).setScale(scale, RoundingMode.HALF_UP);
double scaled = d.doubleValue();
Or you could use:
Math.round(val*Math.pow(10, scale))/Math.pow(10, scale);

To answer the general question of reducing a double's significant digits, and not just the case of printing with System.out.printf:
If you're using Java: Double.parseDouble(String.format("%1.4e", 5.433306166802499E-5))
In Scala, you can use the f string interpolator, or the format method:
val a: Double = 5.433306166802499E-5
val reduced1: Double = f"$a%1.4e".toDouble
val reduced2: Double = "%1.4e".format(a).toDouble
Both are equal: 5.4333e-05

Related

keep trailing zeros for doubla value java [duplicate]

This question already has answers here:
How to round a number to n decimal places in Java
(39 answers)
Closed 8 years ago.
If the value is 200.3456, it should be formatted to 200.34.
If it is 200, then it should be 200.00.
Here's an utility that rounds (instead of truncating) a double to specified number of decimal places.
For example:
round(200.3456, 2); // returns 200.35
Original version; watch out with this
public static double round(double value, int places) {
if (places < 0) throw new IllegalArgumentException();
long factor = (long) Math.pow(10, places);
value = value * factor;
long tmp = Math.round(value);
return (double) tmp / factor;
}
This breaks down badly in corner cases with either a very high number of decimal places (e.g. round(1000.0d, 17)) or large integer part (e.g. round(90080070060.1d, 9)). Thanks to Sloin for pointing this out.
I've been using the above to round "not-too-big" doubles to 2 or 3 decimal places happily for years (for example to clean up time in seconds for logging purposes: 27.987654321987 -> 27.99). But I guess it's best to avoid it, since more reliable ways are readily available, with cleaner code too.
So, use this instead
(Adapted from this answer by Louis Wasserman and this one by Sean Owen.)
public static double round(double value, int places) {
if (places < 0) throw new IllegalArgumentException();
BigDecimal bd = BigDecimal.valueOf(value);
bd = bd.setScale(places, RoundingMode.HALF_UP);
return bd.doubleValue();
}
Note that HALF_UP is the rounding mode "commonly taught at school". Peruse the RoundingMode documentation, if you suspect you need something else such as Bankers’ Rounding.
Of course, if you prefer, you can inline the above into a one-liner:
new BigDecimal(value).setScale(places, RoundingMode.HALF_UP).doubleValue()
And in every case
Always remember that floating point representations using float and double are inexact.
For example, consider these expressions:
999199.1231231235 == 999199.1231231236 // true
1.03 - 0.41 // 0.6200000000000001
For exactness, you want to use BigDecimal. And while at it, use the constructor that takes a String, never the one taking double. For instance, try executing this:
System.out.println(new BigDecimal(1.03).subtract(new BigDecimal(0.41)));
System.out.println(new BigDecimal("1.03").subtract(new BigDecimal("0.41")));
Some excellent further reading on the topic:
Item 48: "Avoid float and double if exact answers are required" in Effective Java (2nd ed) by Joshua Bloch
What Every Programmer Should Know About Floating-Point Arithmetic
If you wanted String formatting instead of (or in addition to) strictly rounding numbers, see the other answers.
Specifically, note that round(200, 0) returns 200.0. If you want to output "200.00", you should first round and then format the result for output (which is perfectly explained in Jesper's answer).
If you just want to print a double with two digits after the decimal point, use something like this:
double value = 200.3456;
System.out.printf("Value: %.2f", value);
If you want to have the result in a String instead of being printed to the console, use String.format() with the same arguments:
String result = String.format("%.2f", value);
Or use class DecimalFormat:
DecimalFormat df = new DecimalFormat("####0.00");
System.out.println("Value: " + df.format(value));
I think this is easier:
double time = 200.3456;
DecimalFormat df = new DecimalFormat("#.##");
time = Double.valueOf(df.format(time));
System.out.println(time); // 200.35
Note that this will actually do the rounding for you, not just formatting.
The easiest way, would be to do a trick like this;
double val = ....;
val = val*100;
val = Math.round(val);
val = val /100;
if val starts at 200.3456 then it goes to 20034.56 then it gets rounded to 20035 then we divide it to get 200.34.
if you wanted to always round down we could always truncate by casting to an int:
double val = ....;
val = val*100;
val = (double)((int) val);
val = val /100;
This technique will work for most cases because for very large doubles (positive or negative) it may overflow. but if you know that your values will be in an appropriate range then this should work for you.
Please use Apache commons math:
Precision.round(10.4567, 2)
function Double round2(Double val) {
return new BigDecimal(val.toString()).setScale(2,RoundingMode.HALF_UP).doubleValue();
}
Note the toString()!!!!
This is because BigDecimal converts the exact binary form of the double!!!
These are the various suggested methods and their fail cases.
// Always Good!
new BigDecimal(val.toString()).setScale(2,RoundingMode.HALF_UP).doubleValue()
Double val = 260.775d; //EXPECTED 260.78
260.77 - WRONG - new BigDecimal(val).setScale(2,RoundingMode.HALF_UP).doubleValue()
Double val = 260.775d; //EXPECTED 260.78
260.77 - TRY AGAIN - Math.round(val * 100.d) / 100.0d
Double val = 256.025d; //EXPECTED 256.03d
256.02 - OOPS - new DecimalFormat("0.00").format(val)
// By default use half even, works if you change mode to half_up
Double val = 256.025d; //EXPECTED 256.03d
256.02 - FAIL - (int)(val * 100 + 0.5) / 100.0;
double value= 200.3456;
DecimalFormat df = new DecimalFormat("0.00");
System.out.println(df.format(value));
If you really want the same double, but rounded in the way you want you can use BigDecimal, for example
new BigDecimal(myValue).setScale(2, RoundingMode.HALF_UP).doubleValue();
double d = 28786.079999999998;
String str = String.format("%1.2f", d);
d = Double.valueOf(str);
For two rounding digits. Very simple and you are basically updating the variable instead of just display purposes which DecimalFormat does.
x = Math.floor(x * 100) / 100;
Rounding a double is usually not what one wants. Instead, use String.format() to represent it in the desired format.
In your question, it seems that you want to avoid rounding the numbers as well? I think .format() will round the numbers using half-up, afaik?
so if you want to round, 200.3456 should be 200.35 for a precision of 2. but in your case, if you just want the first 2 and then discard the rest?
You could multiply it by 100 and then cast to an int (or taking the floor of the number), before dividing by 100 again.
200.3456 * 100 = 20034.56;
(int) 20034.56 = 20034;
20034/100.0 = 200.34;
You might have issues with really really big numbers close to the boundary though. In which case converting to a string and substring'ing it would work just as easily.
value = (int)(value * 100 + 0.5) / 100.0;

Double in 2 decimal format [duplicate]

This question already has answers here:
How to round a number to n decimal places in Java
(39 answers)
Closed 8 years ago.
If the value is 200.3456, it should be formatted to 200.34.
If it is 200, then it should be 200.00.
Here's an utility that rounds (instead of truncating) a double to specified number of decimal places.
For example:
round(200.3456, 2); // returns 200.35
Original version; watch out with this
public static double round(double value, int places) {
if (places < 0) throw new IllegalArgumentException();
long factor = (long) Math.pow(10, places);
value = value * factor;
long tmp = Math.round(value);
return (double) tmp / factor;
}
This breaks down badly in corner cases with either a very high number of decimal places (e.g. round(1000.0d, 17)) or large integer part (e.g. round(90080070060.1d, 9)). Thanks to Sloin for pointing this out.
I've been using the above to round "not-too-big" doubles to 2 or 3 decimal places happily for years (for example to clean up time in seconds for logging purposes: 27.987654321987 -> 27.99). But I guess it's best to avoid it, since more reliable ways are readily available, with cleaner code too.
So, use this instead
(Adapted from this answer by Louis Wasserman and this one by Sean Owen.)
public static double round(double value, int places) {
if (places < 0) throw new IllegalArgumentException();
BigDecimal bd = BigDecimal.valueOf(value);
bd = bd.setScale(places, RoundingMode.HALF_UP);
return bd.doubleValue();
}
Note that HALF_UP is the rounding mode "commonly taught at school". Peruse the RoundingMode documentation, if you suspect you need something else such as Bankers’ Rounding.
Of course, if you prefer, you can inline the above into a one-liner:
new BigDecimal(value).setScale(places, RoundingMode.HALF_UP).doubleValue()
And in every case
Always remember that floating point representations using float and double are inexact.
For example, consider these expressions:
999199.1231231235 == 999199.1231231236 // true
1.03 - 0.41 // 0.6200000000000001
For exactness, you want to use BigDecimal. And while at it, use the constructor that takes a String, never the one taking double. For instance, try executing this:
System.out.println(new BigDecimal(1.03).subtract(new BigDecimal(0.41)));
System.out.println(new BigDecimal("1.03").subtract(new BigDecimal("0.41")));
Some excellent further reading on the topic:
Item 48: "Avoid float and double if exact answers are required" in Effective Java (2nd ed) by Joshua Bloch
What Every Programmer Should Know About Floating-Point Arithmetic
If you wanted String formatting instead of (or in addition to) strictly rounding numbers, see the other answers.
Specifically, note that round(200, 0) returns 200.0. If you want to output "200.00", you should first round and then format the result for output (which is perfectly explained in Jesper's answer).
If you just want to print a double with two digits after the decimal point, use something like this:
double value = 200.3456;
System.out.printf("Value: %.2f", value);
If you want to have the result in a String instead of being printed to the console, use String.format() with the same arguments:
String result = String.format("%.2f", value);
Or use class DecimalFormat:
DecimalFormat df = new DecimalFormat("####0.00");
System.out.println("Value: " + df.format(value));
I think this is easier:
double time = 200.3456;
DecimalFormat df = new DecimalFormat("#.##");
time = Double.valueOf(df.format(time));
System.out.println(time); // 200.35
Note that this will actually do the rounding for you, not just formatting.
The easiest way, would be to do a trick like this;
double val = ....;
val = val*100;
val = Math.round(val);
val = val /100;
if val starts at 200.3456 then it goes to 20034.56 then it gets rounded to 20035 then we divide it to get 200.34.
if you wanted to always round down we could always truncate by casting to an int:
double val = ....;
val = val*100;
val = (double)((int) val);
val = val /100;
This technique will work for most cases because for very large doubles (positive or negative) it may overflow. but if you know that your values will be in an appropriate range then this should work for you.
Please use Apache commons math:
Precision.round(10.4567, 2)
function Double round2(Double val) {
return new BigDecimal(val.toString()).setScale(2,RoundingMode.HALF_UP).doubleValue();
}
Note the toString()!!!!
This is because BigDecimal converts the exact binary form of the double!!!
These are the various suggested methods and their fail cases.
// Always Good!
new BigDecimal(val.toString()).setScale(2,RoundingMode.HALF_UP).doubleValue()
Double val = 260.775d; //EXPECTED 260.78
260.77 - WRONG - new BigDecimal(val).setScale(2,RoundingMode.HALF_UP).doubleValue()
Double val = 260.775d; //EXPECTED 260.78
260.77 - TRY AGAIN - Math.round(val * 100.d) / 100.0d
Double val = 256.025d; //EXPECTED 256.03d
256.02 - OOPS - new DecimalFormat("0.00").format(val)
// By default use half even, works if you change mode to half_up
Double val = 256.025d; //EXPECTED 256.03d
256.02 - FAIL - (int)(val * 100 + 0.5) / 100.0;
double value= 200.3456;
DecimalFormat df = new DecimalFormat("0.00");
System.out.println(df.format(value));
If you really want the same double, but rounded in the way you want you can use BigDecimal, for example
new BigDecimal(myValue).setScale(2, RoundingMode.HALF_UP).doubleValue();
double d = 28786.079999999998;
String str = String.format("%1.2f", d);
d = Double.valueOf(str);
For two rounding digits. Very simple and you are basically updating the variable instead of just display purposes which DecimalFormat does.
x = Math.floor(x * 100) / 100;
Rounding a double is usually not what one wants. Instead, use String.format() to represent it in the desired format.
In your question, it seems that you want to avoid rounding the numbers as well? I think .format() will round the numbers using half-up, afaik?
so if you want to round, 200.3456 should be 200.35 for a precision of 2. but in your case, if you just want the first 2 and then discard the rest?
You could multiply it by 100 and then cast to an int (or taking the floor of the number), before dividing by 100 again.
200.3456 * 100 = 20034.56;
(int) 20034.56 = 20034;
20034/100.0 = 200.34;
You might have issues with really really big numbers close to the boundary though. In which case converting to a string and substring'ing it would work just as easily.
value = (int)(value * 100 + 0.5) / 100.0;

How to always round off upto 2 decimal places in java

I have tried the following code but it is not working in a particular case.
Eg: Suppose, I have a double value=2.5045 and i want it to be rounded off upto two decimal places using the below code.After rounding off, i get the answer as 2.5. But I want the answer to be 2.50 instead. In this case,zero is trimmed off. Is there any way to retain the zero so as to get the desired answer as 2.50 after rounding off.
private static DecimalFormat twoDForm = new DecimalFormat("#.##");
public static double roundTwoDecimals(double amount) {
return Double.valueOf(twoDForm.format(amount));
}
try this pattern
new DecimalFormat("0.00");
but this will change only formatting, double cannot hold number of digits after decimal poin, try BigDecimal
BigDecimal bd = new BigDecimal(2.5045).setScale(2, RoundingMode.HALF_UP);
Look at the documentation for DecimalFormat. For # it says:
Digit, zero shows as absent
0 is probably what you want:
Digit
So what you are looking for is either "0.00" or "#.00" as a format string, depending on whether you want the first digit before the period, to be visible in case the numbers absolute value is smalle than 0.
Try this
DecimalFormat format = new DecimalFormat("#");
format.setMinimumFractionDigits(2);
answer.setText(format.format(data2));
Try This
double d = 4.85999999999;
long l = (int)Math.round(d * 100); // truncates
d = l / 100.0;
You are returning a double. But double or Double are objects representing a number and don't carry any formatting information. Ìf you need to output two decimal places the point to do this is when you convert your double to a String.
use # if you want to ignore 0
new DecimalFormat("###,#0.00").format(d)
There is another way to achieve this . I have already posted answer in post
will just answer again here. As we will require rounding off values many times .
public class RoundingNumbers {
public static void main(String args[]){
double number = 2.5045;
int decimalsToConsider = 2;
BigDecimal bigDecimal = new BigDecimal(number);
BigDecimal roundedWithScale = bigDecimal.setScale(decimalsToConsider, BigDecimal.ROUND_HALF_UP);
System.out.println("Rounded value with setting scale = "+roundedWithScale);
bigDecimal = new BigDecimal(number);
BigDecimal roundedValueWithDivideLogic = bigDecimal.divide(BigDecimal.ONE,decimalsToConsider,BigDecimal.ROUND_HALF_UP);
System.out.println("Rounded value with Dividing by one = "+roundedValueWithDivideLogic);
}
}
Output we will get is
Rounded value with setting scale = 2.50
Rounded value with Dividing by one = 2.50
double kilobytes = 1205.6358;
double newKB = Math.round(kilobytes*100.0)/100.0;
DecimalFormat df = new DecimalFormat("###.##");
System.out.println("kilobytes (DecimalFormat) : " + df.format(kilobytes));
Try this if u are still getting the above problem

How do I print a double value without scientific notation using Java?

I want to print a double value in Java without exponential form.
double dexp = 12345678;
System.out.println("dexp: "+dexp);
It shows this E notation: 1.2345678E7.
I want it to print it like this: 12345678
What is the best way to prevent this?
Java prevent E notation in a double:
Five different ways to convert a double to a normal number:
import java.math.BigDecimal;
import java.text.DecimalFormat;
public class Runner {
public static void main(String[] args) {
double myvalue = 0.00000021d;
//Option 1 Print bare double.
System.out.println(myvalue);
//Option2, use decimalFormat.
DecimalFormat df = new DecimalFormat("#");
df.setMaximumFractionDigits(8);
System.out.println(df.format(myvalue));
//Option 3, use printf.
System.out.printf("%.9f", myvalue);
System.out.println();
//Option 4, convert toBigDecimal and ask for toPlainString().
System.out.print(new BigDecimal(myvalue).toPlainString());
System.out.println();
//Option 5, String.format
System.out.println(String.format("%.12f", myvalue));
}
}
This program prints:
2.1E-7
.00000021
0.000000210
0.000000210000000000000001085015324114868562332958390470594167709350585
0.000000210000
Which are all the same value.
Protip: If you are confused as to why those random digits appear beyond a certain threshold in the double value, this video explains: computerphile why does 0.1+0.2 equal 0.30000000000001?
http://youtube.com/watch?v=PZRI1IfStY0
You could use printf() with %f:
double dexp = 12345678;
System.out.printf("dexp: %f\n", dexp);
This will print dexp: 12345678.000000. If you don't want the fractional part, use
System.out.printf("dexp: %.0f\n", dexp);
0 in %.0f means 0 places in fractional part i.e no fractional part. If you want to print fractional part with desired number of decimal places then instead of 0 just provide the number like this %.8f. By default fractional part is printed up to 6 decimal places.
This uses the format specifier language explained in the documentation.
The default toString() format used in your original code is spelled out here.
In short:
If you want to get rid of trailing zeros and Locale problems, then you should use:
double myValue = 0.00000021d;
DecimalFormat df = new DecimalFormat("0", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
df.setMaximumFractionDigits(340); // 340 = DecimalFormat.DOUBLE_FRACTION_DIGITS
System.out.println(df.format(myValue)); // Output: 0.00000021
Explanation:
Why other answers did not suit me:
Double.toString() or System.out.println or FloatingDecimal.toJavaFormatString uses scientific notations if double is less than 10^-3 or greater than or equal to 10^7
By using %f, the default decimal precision is 6, otherwise you can hardcode it, but it results in extra zeros added if you have fewer decimals. Example:
double myValue = 0.00000021d;
String.format("%.12f", myvalue); // Output: 0.000000210000
By using setMaximumFractionDigits(0); or %.0f you remove any decimal precision, which is fine for integers/longs, but not for double:
double myValue = 0.00000021d;
System.out.println(String.format("%.0f", myvalue)); // Output: 0
DecimalFormat df = new DecimalFormat("0");
System.out.println(df.format(myValue)); // Output: 0
By using DecimalFormat, you are local dependent. In French locale, the decimal separator is a comma, not a point:
double myValue = 0.00000021d;
DecimalFormat df = new DecimalFormat("0");
df.setMaximumFractionDigits(340);
System.out.println(df.format(myvalue)); // Output: 0,00000021
Using the ENGLISH locale makes sure you get a point for decimal separator, wherever your program will run.
Why using 340 then for setMaximumFractionDigits?
Two reasons:
setMaximumFractionDigits accepts an integer, but its implementation has a maximum digits allowed of DecimalFormat.DOUBLE_FRACTION_DIGITS which equals 340
Double.MIN_VALUE = 4.9E-324 so with 340 digits you are sure not to round your double and lose precision.
You can try it with DecimalFormat. With this class you are very flexible in parsing your numbers.
You can exactly set the pattern you want to use.
In your case for example:
double test = 12345678;
DecimalFormat df = new DecimalFormat("#");
df.setMaximumFractionDigits(0);
System.out.println(df.format(test)); //12345678
I've got another solution involving BigDecimal's toPlainString(), but this time using the String-constructor, which is recommended in the javadoc:
this constructor is compatible with the values returned by Float.toString and Double.toString. This is generally the preferred way to convert a float or double into a BigDecimal, as it doesn't suffer from the unpredictability of the BigDecimal(double) constructor.
It looks like this in its shortest form:
return new BigDecimal(myDouble.toString()).stripTrailingZeros().toPlainString();
NaN and infinite values have to be checked extra, so looks like this in its complete form:
public static String doubleToString(Double d) {
if (d == null)
return null;
if (d.isNaN() || d.isInfinite())
return d.toString();
return new BigDecimal(d.toString()).stripTrailingZeros().toPlainString();
}
This can also be copied/pasted to work nicely with Float.
For Java 7 and below, this results in "0.0" for any zero-valued Doubles, so you would need to add:
if (d.doubleValue() == 0)
return "0";
Java/Kotlin compiler converts any value greater than 9999999 (greater than or equal to 10 million) to scientific notation ie. Epsilion notation.
Ex: 12345678 is converted to 1.2345678E7
Use this code to avoid automatic conversion to scientific notation:
fun setTotalSalesValue(String total) {
var valueWithoutEpsilon = total.toBigDecimal()
/* Set the converted value to your android text view using setText() function */
salesTextView.setText( valueWithoutEpsilon.toPlainString() )
}
This will work as long as your number is a whole number:
double dnexp = 12345678;
System.out.println("dexp: " + (long)dexp);
If the double variable has precision after the decimal point it will truncate it.
I needed to convert some double to currency values and found that most of the solutions were OK, but not for me.
The DecimalFormat was eventually the way for me, so here is what I've done:
public String foo(double value) //Got here 6.743240136E7 or something..
{
DecimalFormat formatter;
if(value - (int)value > 0.0)
formatter = new DecimalFormat("0.00"); // Here you can also deal with rounding if you wish..
else
formatter = new DecimalFormat("0");
return formatter.format(value);
}
As you can see, if the number is natural I get - say - 20000000 instead of 2E7 (etc.) - without any decimal point.
And if it's decimal, I get only two decimal digits.
I think everyone had the right idea, but all answers were not straightforward.
I can see this being a very useful piece of code. Here is a snippet of what will work:
System.out.println(String.format("%.8f", EnterYourDoubleVariableHere));
the ".8" is where you set the number of decimal places you would like to show.
I am using Eclipse and it worked no problem.
Hope this was helpful. I would appreciate any feedback!
The following code detects if the provided number is presented in scientific notation. If so it is represented in normal presentation with a maximum of '25' digits.
static String convertFromScientificNotation(double number) {
// Check if in scientific notation
if (String.valueOf(number).toLowerCase().contains("e")) {
System.out.println("The scientific notation number'"
+ number
+ "' detected, it will be converted to normal representation with 25 maximum fraction digits.");
NumberFormat formatter = new DecimalFormat();
formatter.setMaximumFractionDigits(25);
return formatter.format(number);
} else
return String.valueOf(number);
}
This may be a tangent.... but if you need to put a numerical value as an integer (that is too big to be an integer) into a serializer (JSON, etc.) then you probably want "BigInterger"
Example:
value is a string - 7515904334
We need to represent it as a numerical in a Json message:
{
"contact_phone":"800220-3333",
"servicer_id":7515904334,
"servicer_name":"SOME CORPORATION"
}
We can't print it or we'll get this:
{
"contact_phone":"800220-3333",
"servicer_id":"7515904334",
"servicer_name":"SOME CORPORATION"
}
Adding the value to the node like this produces the desired outcome:
BigInteger.valueOf(Long.parseLong(value, 10))
I'm not sure this is really on-topic, but since this question was my top hit when I searched for my solution, I thought I would share here for the benefit of others, lie me, who search poorly. :D
use String.format ("%.0f", number)
%.0f for zero decimal
String numSring = String.format ("%.0f", firstNumber);
System.out.println(numString);
I had this same problem in my production code when I was using it as a string input to a math.Eval() function which takes a string like "x + 20 / 50"
I looked at hundreds of articles... In the end I went with this because of the speed. And because the Eval function was going to convert it back into its own number format eventually and math.Eval() didn't support the trailing E-07 that other methods returned, and anything over 5 dp was too much detail for my application anyway.
This is now used in production code for an application that has 1,000+ users...
double value = 0.0002111d;
String s = Double.toString(((int)(value * 100000.0d))/100000.0d); // Round to 5 dp
s display as: 0.00021
This will work not only for a whole numbers:
double dexp = 12345678.12345678;
BigDecimal bigDecimal = new BigDecimal(Double.toString(dexp));
System.out.println("dexp: "+ bigDecimal.toPlainString());
My solution:
String str = String.format ("%.0f", yourDouble);
For integer values represented by a double, you can use this code, which is much faster than the other solutions.
public static String doubleToString(final double d) {
// check for integer, also see https://stackoverflow.com/a/9898613/868941 and
// https://github.com/google/guava/blob/master/guava/src/com/google/common/math/DoubleMath.java
if (isMathematicalInteger(d)) {
return Long.toString((long)d);
} else {
// or use any of the solutions provided by others, this is the best
DecimalFormat df =
new DecimalFormat("0", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
df.setMaximumFractionDigits(340); // 340 = DecimalFormat.DOUBLE_FRACTION_DIGITS
return df.format(d);
}
}
// Java 8+
public static boolean isMathematicalInteger(final double d) {
return StrictMath.rint(d) == d && Double.isFinite(d);
}
This works for me. The output will be a String.
String.format("%.12f", myvalue);
Good way to convert scientific e notation
String.valueOf(YourDoubleValue.longValue())

Java : No matter which method I use, I cannot round a double to 4 decimals

I need to round some Doubles to 3 to 4 decimals. I tried 3 different methods, none of them work.
For most of the double I have, it works, but I keep having such doubles anyway :
0.12919999999999998
0.12365000000000001
36371.922099999996
I tried the following methods so far :
-- 1
(double) Math.round(someDouble * 10000) / 10000
-- 2
DecimalFormat twoDForm = new DecimalFormat("0.0000");
twoDForm.format(someDouble);
-- 3
BigDecimal bd = new BigDecimal(someDouble);
bd = bd.setScale(4, BigDecimal.ROUND_HALF_UP);
Does anyone have the magic solution I am looking for :) ?
Thank you !
NOTE :
Here is the full code :
// Processing
long start = System.nanoTime();
for (int i = 0; i < loopSize; i++) {
process();
}
// end timer
long absTime = System.nanoTime() - start;
double absTimeMilli = absTime * 1e-6;
DecimalFormat t = new DecimalFormat("###.####");
context.setTotalTime(Double.valueOf(t.format(absTimeMilli)));
context.setUnit(TimeUnit.SECONDS);
context.setMeanTime(Double.valueOf(t.format(absTimeMilli / Const.BENCH_LOOP_COUNT)));
context.setExecPerTimeUnit(Double.valueOf(t.format(loopSize / (absTimeMilli*1e-3))));
If you are storing the result back into a double type (your first example hints that you are), then this will happen. Double cannot store some numbers.
Once you have rounded, store the result in a BigDecimal or a String.
Updated - see comments below
May have misunderstood your comment, but something like this.
// this.totalTime += (1.0/someInteger)*myValue
BigDecimal ratio = BigDecimal.ONE.divide(new BigDecimal(someInteger));
totalTime = totalTime.add(ratio.multiply(myValue));
double val = 2.33333333;
DecimalFormat df2 = new DecimalFormat("###.####");
Try this.
A double cannot represent all possible decimal values due to the limitations in floating point representation (see http://en.wikipedia.org/wiki/Floating_point for more info or just google "floating ponint precision problem"). So if you need to process the rounded values simply store them in a BigDecimal, round it and keep working with that instead of going back to a double.
here is what i know so far ... to round a double you should use BigDecimal like this:
double yourDouble = 0.123456789;
int scale = 3;
double yourRoundedDouble = new BigDecimal(yourDouble).setScale(scale, RoundingMode.HALF_UP).doubleValue();
the result would be : 0.123.
note that "scale" is the number of digits you want to have after the point.
Hope this helps.
I am not sure what are you looking for, I do these sort of calculations like this
double p=36371.922099999996;
p=Math.round(p *10000.0000)/10000.0000;
System.out.println(p);
and I get 36371.9221
Try it

Categories

Resources