Is there a way to make a NumberFormatter that does the following:
If the Double is a whole number like 5.0, display "5"
If the Double is a decimal like 5.6, display "5.6"
I know this is an old question but this should do exactly what you asked:
var myNumber:Double = 0.0 // set to 5.0 or 5.6 to see result
let formatter = NumberFormatter()
formatter.maximumFractionDigits = 4
let x = formatter.string(from: NSNumber(value: myNumber)) ?? "$\(myNumber)"
print("x = \(x)")
double someNum = 5.6d;
DecimalFormat df = new DecimalFormat("#.#");
String num = df.format(someNum);
if (num.substring(num.length - 1).equals("0")) {
num = num.substring(0, num.length - 2);
}
System.out.println(num);
The DecimalFormat instance formats the double into a string. The code checks the tenth place of precision, i.e. the first digit to the right of the decimal place, and if it be zero, then it shows only whole numbers. Otherwise, it shows the full precision.
Related
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;
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 round "3.416436417734133 in "3.416436418" (nine positions after point) but also if i have "3.7578845854848E41" it round to "3.7578845855E41"? i'm trying to realyze a calculator..
You can use DecimalFormat, I am not sure about the other numbers but currently you have numbers which have single digit before the decimal point. So, check following example where you can format the double value. Note one more thing that you may need to change format pattern for your use case.
FOR EXAMPLE :
double d = 3.7578845854848E41;
double d2 = 3.416436417734133;
DecimalFormat f = new DecimalFormat("0.#########E0");
System.out.println(f.format(d));
System.out.println(f.format(d2));
OUTPUT :
3.757884585E41
3.416436418E0
//Replace E0 with space as format returns String
EDIT :
Because of your default locale. You can change local like this,
//Change locale
DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols(Locale.US);
DecimalFormat f = new DecimalFormat("0.#########E0", decimalFormatSymbols);
//And than use decimal format
You may use BigDecimal to add a "scale" to your double value :
Double d = 3.416436417734133;
BigDecimal round = new BigDecimal(d);
round = round.setScale(9, BigDecimal.ROUND_CEILING);
System.out.println(round);
You can use this code.
BigDecimal aDecimal = new BigDecimal(3.416436417734133);
BigDecimal another = aDecimal.setScale(9, aDecimal.ROUND_HALF_UP);
System.out.println("another: " + another);
System.out.println(new BigDecimal(3.7578845854848E41,new
MathContext(11,RoundingMode.CEILING)));
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
I am truncating a float here.But my value is getting rounded.I do not want that.E.g If my value is 12.989 -> it should be printed as 12.98 only. Can someone help
I cannot use decimal format's SetRoundingMode because that is supported from java 1.6 only.
Mine is 1.5 JDK. CAn someone help me out without using SetRoundingMode() Method????
String pattern = "##,##0.00";
NumberFormat nf = NumberFormat.getNumberInstance();
DecimalFormat df = (DecimalFormat)nf;
double fPart;
Float value=233.989f;
String dstr = String.valueOf(value);
dstr = dstr.substring(dstr.indexOf(".")+1);
Long db = Long.valueOf(dstr);
if(db > 0){
df.applyPattern(pattern);
System.out.println("input="+value+", fPart="+dstr);
}
String output = df.format(value);
System.out.println(output);
You can always use old school trick, multiply by 10^n, truncate, divide by 10^n:
float x = 233.989f;
x = (float)(Math.floor(x * 100) / 100);
I've also experimented with BigDecimal:
MathContext mc = new MathContext(5, RoundingMode.FLOOR)
BigDecimal decimal = new BigDecimal(233.989, mc);
System.out.println(decimal);
It does the job but you have to specify total number of digits. You can't just say I want 2 decimal places and I don't care about digits left of decimal point. That's way first parameter of MathContext is 5, not 2. If you opt for this approach, you can quickly calculate non decimal digits with Math.Ceil(Math.log10(x)).
Note:
When dividing (first approach) at least one of operands must be floating point (float or double)
When working with strings (you code), it's not safe to presume that '.' is decimal separator
Truncating decimals with Math.floor only works for positive values
Not sure If I understood you problem correclty. But If you want to truncate without rounding up or down, you can use just like
DecimalFormat df = new DecimalFormat("##.##");
df.format(12.912385);
You can use regular expressions to get the second digit after "." and then subtract the string from the beginning to that position and then transform the string into a float or double.
Pattern pattern = Pattern.compile("regular expression");
Matcher matcher = pattern.matcher("your string");
if(matcher.find())
{
int poz_begin = matcher.start();
int poz_end = matcher.end();
}