I got this problem with double (decimals).
When a double = 1.234567 Then I use String.format("%.3f", myString);
So the result is 1.234
But when my double is 10
The result will be 10,000
I want this to be 10
Is their a way to say that he only needs to show the decimals when it is "usefull"?
I saw some posts about this, but that was php or c#, couldn't find something for android/java about this (maybe I don't look good).
Hope you guys can help me out with this.
Edit, for now I use something like this: myString.replace(",000", "");
But I think their is a more "friendly" code for this.
The DecimalFormat with the # parameter is the way to go:
public static void main(String[] args) {
double d1 = 1.234567;
double d2 = 2;
NumberFormat nf = new DecimalFormat("##.###");
System.out.println(nf.format(d1));
System.out.println(nf.format(d2));
}
Will result in
1.235
2
Don't use doubles. You can lose some precision. Here's a general purpose function.
public static double round(double unrounded, int precision, int roundingMode)
{
BigDecimal bd = new BigDecimal(unrounded);
BigDecimal rounded = bd.setScale(precision, roundingMode);
return rounded.doubleValue();
}
You can call it with
round(yourNumber, 3, BigDecimal.ROUND_HALF_UP);
"precision" being the number of decimal points you desire.
Copy from Here.
Try it
double amount = 1.234567 ;
NumberFormat formatter = new DecimalFormat("##.###");
System.out.println("The Decimal Value is:"+formatter.format(amount));
Related
I need to format a float to "n"decimal places.
was trying to BigDecimal, but the return value is not correct...
public static float Redondear(float pNumero, int pCantidadDecimales) {
// the function is call with the values Redondear(625.3f, 2)
BigDecimal value = new BigDecimal(pNumero);
value = value.setScale(pCantidadDecimales, RoundingMode.HALF_EVEN); // here the value is correct (625.30)
return value.floatValue(); // but here the values is 625.3
}
I need to return a float value with the number of decimal places that I specify.
I need Float value return not Double
.
You may also pass the float value, and use:
String.format("%.2f", floatValue);
Documentation
Take a look at DecimalFormat. You can easily use it to take a number and give it a set number of decimal places.
Edit: Example
Try this this helped me a lot
BigDecimal roundfinalPrice = new BigDecimal(5652.25622f).setScale(2,BigDecimal.ROUND_HALF_UP);
Result will be
roundfinalPrice --> 5652.26
Of note, use of DecimalFormat constructor is discouraged. The javadoc for this class states:
In general, do not call the DecimalFormat constructors directly, since the NumberFormat factory methods may return subclasses other than DecimalFormat.
https://docs.oracle.com/javase/8/docs/api/java/text/DecimalFormat.html
So what you need to do is (for instance):
NumberFormat formatter = NumberFormat.getInstance(Locale.US);
formatter.setMaximumFractionDigits(2);
formatter.setMinimumFractionDigits(2);
formatter.setRoundingMode(RoundingMode.HALF_UP);
Float formatedFloat = new Float(formatter.format(floatValue));
Here's a quick sample using the DecimalFormat class mentioned by Nick.
float f = 12.345f;
DecimalFormat df = new DecimalFormat("#.00");
System.out.println(df.format(f));
The output of the print statement will be 12.35. Notice that it will round it for you.
Kinda surprised nobody's pointed out the direct way to do it, which is easy enough.
double roundToDecimalPlaces(double value, int decimalPlaces)
{
double shift = Math.pow(10,decimalPlaces);
return Math.round(value*shift)/shift;
}
Pretty sure this does not do half-even rounding though.
For what it's worth, half-even rounding is going to be chaotic and unpredictable any time you mix binary-based floating-point values with base-10 arithmetic. I'm pretty sure it cannot be done. The basic problem is that a value like 1.105 cannot be represented exactly in floating point. The floating point value is going to be something like 1.105000000000001, or 1.104999999999999. So any attempt to perform half-even rounding is going trip up on representational encoding errors.
IEEE floating point implementations will do half-rounding, but they do binary half-rounding, not decimal half-rounding. So you're probably ok
public static double roundToDouble(float d, int decimalPlace) {
BigDecimal bd = new BigDecimal(Float.toString(d));
bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
return bd.doubleValue();
}
This is a much less professional and much more expensive way but it should be easier to understand and more helpful for beginners.
public static float roundFloat(float F, int roundTo){
String num = "#########.";
for (int count = 0; count < roundTo; count++){
num += "0";
}
DecimalFormat df = new DecimalFormat(num);
df.setRoundingMode(RoundingMode.HALF_UP);
String S = df.format(F);
F = Float.parseFloat(S);
return F;
}
I was looking for an answer to this question and later I developed a method! :) A fair warning, it's rounding up the value.
private float limitDigits(float number) {
return Float.valueOf(String.format(Locale.getDefault(), "%.2f", number));
}
I think what you want ist
return value.toString();
and use the return value to display.
value.floatValue();
will always return 625.3 because its mainly used to calculate something.
You can use Decimal format if you want to format number into a string, for example:
String a = "123455";
System.out.println(new
DecimalFormat(".0").format(Float.valueOf(a)));
The output of this code will be:
123455.0
You can add more zeros to the decimal format, depends on the output that you want.
I'm working on a project which requires me to have double values at exactly 2 decimal place. Using some math, I currently have most numbers rounded correctly, except if there are trailing zeros. I want to keep these 0's for results like 0.00 in particular This list is displayed in a TableView, so therefore must be sortable numerically. I'd like the double values to actually be doubles so that it may properly sort.
Is there any way I can keep 2 decimal places without String.format?
Thank you in advance.
You can use DecimalFormat
DecimalFormat df = new DecimalFormat("#.00");
00 = exactly two decimal places.
But this will give to you a String that you can convert again to a double, if you don't want to have this String-conversion check this question to see how it can be achieved using BigDecimal.
IMHO, if this is not for learning pourposes DecimalFormat will be enough for you. True, you will have to use String in some moment of the conversion, but you will only read and store double values and your sorting will be the correct...
This answer expands on the suggestion to use java.math.BigDecimal rather than double.
It is better for this application than double because every two decimal place number is exactly representable in BigDecimal. The rounding from an arbitrary double-representable value down to two decimal places can be easily done according to any of several rounding modes, including the one used for double arithmetic.
On the other hand, it is better than String because the natural sort order is numeric value.
Here is a short demo program illustrating these points:
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class Test {
public static void main(String[] args) throws Throwable {
List<BigDecimal> list = new ArrayList<BigDecimal>();
double[] in = {
3.5,
Math.PI,
-100.123456,
1e6
};
System.out.println("Original doubles: "+Arrays.toString(in));
for(double d : in){
list.add(doubleToBigDecimal(d,1));
}
System.out.println("Before sorting: " + list);
Collections.sort(list);
System.out.println("After sorting: " + list);
}
public static BigDecimal doubleToBigDecimal(double in, int places) {
BigDecimal result = new BigDecimal(in).setScale(2,
BigDecimal.ROUND_HALF_EVEN);
return result;
}
}
Output:
Original doubles: [3.5, 3.141592653589793, -100.123456, 1000000.0]
Before sorting: [3.50, 3.14, -100.12, 1000000.00]
After sorting: [-100.12, 3.14, 3.50, 1000000.00]
You can use DecimalFormat, Just set format in DecimalFormat's constructor as your required 2dp so:
double d = 1.234567;
DecimalFormat df = new DecimalFormat("#.##");
System.out.print(df.format(d));
output:
1.23
this code will round the decimal upto to decimal places However it's result will be not upto 2 decimal if value it self is not minimum 2 decimal places. e.g.
double d = 1.2;
DecimalFormat df = new DecimalFormat("#.##");
System.out.print(df.format(d));
output:
1.2
as Thisaru Guruge said and Jordi Castilla answer you can use like:
double d = 1.2;
DecimalFormat df = new DecimalFormat("#.00");
System.out.print(df.format(d));
output:
1.20
You can try BigDecimal, or you can simply create your own object that implements the Comparable interface for sorting and has a toString() method that outputs the value formatted to two decimal places.
class TableValue implements Comparable<TableValue> {
double value;
public TableValue(double value) {
this.value = value;
}
public int compareTo(TableValue o) {
return Double.compare(this.value, o.value);
}
public String toString() {
DecimalFormat df = new DecimalFormat("0.00");
return df.format(value);
}
}
Doubles are imprecise, BigDecimal has an extra attribute: its precision.
So new BigDecimal("5.20") would have a precision of 2, whereas double 5.20 * 10000 probably sufficiently deviates from 52000.0.
Mind the avoidable new BigDecimal(5.20) neither knows a precision, neither is precise.
BigDecimal unfortunately has a COBOListic usage.
You can use DecimalFormat class upto how much precision point you want you can set in class constructor suppose you want 2 precision you can set like
Double total= 12.15356789;
DecimalFormat df = new DecimalFormat("##.00");
Format the value using format method
String dx = df.format(total);
This will return String value of your Double value if you want Double with formatted 2 precision then use below line of code
Double totalVal = Double.valueOf(df.format(total));
This will return you Double value with 2 precision output would be like 12.15
I'm trying to convert some string values in number using DecimalFormat. I try to explain you my problem in a better way:
I have the following method:
private BigDecimal loadBigDecimal(String value){
BigDecimal bigDecimalToReturn = null;
DecimalFormat df = new DecimalFormat("##.###");
bigDecimalToReturn = new BigDecimal(df.parse(value).doubleValue());
return bigDecimalToReturn;
}
Now if I try to run the method:
BigDeciaml dec = myObject.loadBigDecimal("120,11");
The value of dec is 120.1099999999999994315658113919198513031005859375.
Why decimalFormat is changing the scale of my value?
You are doing conversion to double and backwards. That's unnecessary and introduces rounding errors. You should use the following code:
private BigDecimal loadBigDecimal(String value) throws ParseException {
DecimalFormat df = new DecimalFormat("##.###");
df.setParseBigDecimal(true);
return (BigDecimal) df.parse(value);
}
Doubles are only approximations. That is correct for a double. If you want a specific scale, you need to tell it in the BigDecimal constructor.
That is because of the df.parse(value).doubleValue() call. At this point, the value is converted to a double.
double represent plus or minus the sum of powers of 2 (with positive and negative exponents).
One can write 120 as 64+32+16+8.
But one can't write 0.11 as a finite sum of power of 2.
So there is an approximation.
0.1099999999999994315658113919198513031005859375
Which is a sum of power of 2.
It's look like BigDecimal as a constructor with a string for parameter. Maybe you can just use it.
BigDecimal dec = new BigDecimal("120,11");
I am currently trying to write a program which rounds a "double" variable to two decimal places.
I have the method:
DecimalFormat df = new DecimalFormat("#.00");
However, when I apply the method:
double x = df.format(y-z);
I get an error telling me a "double" was expected but a "string" was found.
Any suggestions as to how to fix this?
Thanks!
Try this
#Test
public void test() {
int f = 100;
double d = 123.456;
double temp = d * f;
double rounded = Math.round(temp);
double to2dp = rounded / f;
Assert.assertEquals(123.46, to2dp, 0.00001);
}
The f = 100 is fro 2dp. You would use f = 10 for 1dp etc
If you are using doubles to store/calculate currency values, then you will likely find yourself in a world of pain with rounding. Been there, done that, got the scars.
I highly recommend that you use BigDecimal values for ALL currency values, and do not even involve doubles in the instantiation. Always use the String constructor.
See related questions here and here.
In a comment on my other answer, Gary Rowe has suggested the use of Joda Money as a solution.
Now while this may be a fine product, and I have to admit that I have not tried it, I am a bit concerned about the following example in their documentation:
// multiplies by 3.5 with rounding
money = money.multipliedBy(3.5d, RoundingMode.DOWN);
Now this is an interesting example because they have used a double amount which can be represented exactly using double precision.
To illustrate this, let's take the following unit test as an example:
double d1 = 3.5d;
BigDecimal bd1 = new BigDecimal(d1);
System.out.println("BD version of " + d1 + " = " + bd1);
BigDecimal bd2 = new BigDecimal("10000000");
BigDecimal bd3 = bd2.multiply(bd1);
System.out.println("Result in bd3 = " + bd3);
This yields the following output:
BD version of 3.5 = 3.5
Result in bd3 = 35000000.0
However, if you change the '3.5d' to '3.4d', you get a very different result:
BD version of 3.4 = 3.399999999999999911182158029987476766109466552734375
Result in bd3 = 33999999.999999999111821580299874767661094665527343750000000
Now the Joda Money classes may deal with this (somehow), but introducing any double precision numbers into the mix is fraught with danger.
Gary, perhaps you could comment about the result of a similar calculation in Joda Money.
I need to format a float to "n"decimal places.
was trying to BigDecimal, but the return value is not correct...
public static float Redondear(float pNumero, int pCantidadDecimales) {
// the function is call with the values Redondear(625.3f, 2)
BigDecimal value = new BigDecimal(pNumero);
value = value.setScale(pCantidadDecimales, RoundingMode.HALF_EVEN); // here the value is correct (625.30)
return value.floatValue(); // but here the values is 625.3
}
I need to return a float value with the number of decimal places that I specify.
I need Float value return not Double
.
You may also pass the float value, and use:
String.format("%.2f", floatValue);
Documentation
Take a look at DecimalFormat. You can easily use it to take a number and give it a set number of decimal places.
Edit: Example
Try this this helped me a lot
BigDecimal roundfinalPrice = new BigDecimal(5652.25622f).setScale(2,BigDecimal.ROUND_HALF_UP);
Result will be
roundfinalPrice --> 5652.26
Of note, use of DecimalFormat constructor is discouraged. The javadoc for this class states:
In general, do not call the DecimalFormat constructors directly, since the NumberFormat factory methods may return subclasses other than DecimalFormat.
https://docs.oracle.com/javase/8/docs/api/java/text/DecimalFormat.html
So what you need to do is (for instance):
NumberFormat formatter = NumberFormat.getInstance(Locale.US);
formatter.setMaximumFractionDigits(2);
formatter.setMinimumFractionDigits(2);
formatter.setRoundingMode(RoundingMode.HALF_UP);
Float formatedFloat = new Float(formatter.format(floatValue));
Here's a quick sample using the DecimalFormat class mentioned by Nick.
float f = 12.345f;
DecimalFormat df = new DecimalFormat("#.00");
System.out.println(df.format(f));
The output of the print statement will be 12.35. Notice that it will round it for you.
Kinda surprised nobody's pointed out the direct way to do it, which is easy enough.
double roundToDecimalPlaces(double value, int decimalPlaces)
{
double shift = Math.pow(10,decimalPlaces);
return Math.round(value*shift)/shift;
}
Pretty sure this does not do half-even rounding though.
For what it's worth, half-even rounding is going to be chaotic and unpredictable any time you mix binary-based floating-point values with base-10 arithmetic. I'm pretty sure it cannot be done. The basic problem is that a value like 1.105 cannot be represented exactly in floating point. The floating point value is going to be something like 1.105000000000001, or 1.104999999999999. So any attempt to perform half-even rounding is going trip up on representational encoding errors.
IEEE floating point implementations will do half-rounding, but they do binary half-rounding, not decimal half-rounding. So you're probably ok
public static double roundToDouble(float d, int decimalPlace) {
BigDecimal bd = new BigDecimal(Float.toString(d));
bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
return bd.doubleValue();
}
This is a much less professional and much more expensive way but it should be easier to understand and more helpful for beginners.
public static float roundFloat(float F, int roundTo){
String num = "#########.";
for (int count = 0; count < roundTo; count++){
num += "0";
}
DecimalFormat df = new DecimalFormat(num);
df.setRoundingMode(RoundingMode.HALF_UP);
String S = df.format(F);
F = Float.parseFloat(S);
return F;
}
I was looking for an answer to this question and later I developed a method! :) A fair warning, it's rounding up the value.
private float limitDigits(float number) {
return Float.valueOf(String.format(Locale.getDefault(), "%.2f", number));
}
I think what you want ist
return value.toString();
and use the return value to display.
value.floatValue();
will always return 625.3 because its mainly used to calculate something.
You can use Decimal format if you want to format number into a string, for example:
String a = "123455";
System.out.println(new
DecimalFormat(".0").format(Float.valueOf(a)));
The output of this code will be:
123455.0
You can add more zeros to the decimal format, depends on the output that you want.