Java - double constant number of decimal places [duplicate] - java

This question already has answers here:
fixed point arithmetics in java with fast performance
(4 answers)
Closed 7 years ago.
I have two double variables:
double a = 1.109
double b = 5.0E-5;
But b is changable and I want to achieve fixed numbers of decimal places depending of b number, for example above I want achieve this result:
Result = 1.10900
But not only print, I need to send it to other method and my double must have fixed numbers of decimal places like in example.

It sounds like you want arbitrary precision on the actual value (as opposed to just output). double doesn't give you that. BigDecimal does though. Its BigDecimal(String) constructor sets the value and the scale (number of places to the right of the decimal) from a string, so:
BigDecimal d = new BigDecimal("1.10900");
BigDecimal then gives you various math operations to stay within that scale, with various rounding options.
If at some point you need to get the double value of the BigDecimal, you can use its doubleValue method. But note that at that point, again, you don't have a fixed number of places to the right of the decimal anymore.
Here's an example contrasting BigDecimal and double (Live Copy):
import java.math.*;
class Example
{
public static void main (String[] args) throws java.lang.Exception
{
BigDecimal bd = new BigDecimal("1.10900");
bd = bd.divide(new BigDecimal("27"), BigDecimal.ROUND_HALF_DOWN);
System.out.println("1.109 / 27 using BigDecimal to five places: " + bd);
double d = 1.109;
d = d / 27.0;
System.out.println("1.109 / 27 using double: " + d);
}
}
Output:
1.109 / 27 using BigDecimal to five places: 0.04107
1.109 / 27 using double: 0.041074074074074075

Try using a number formatter:
NumberFormat formatter = new DecimalFormat("#0.00000");
double a = 1.109;
double b = 5.0E-5;
System.out.println(a);
System.out.println(b);
Output:
1.10900
0.00005

A simple solution is to round the result as needed. This is not only faster than using BigDecimal it can be less error prone as Java doesn't have language support for BigDecimal making it harder to write/read and validate. A simple method for rounding half up for 5 decimal spaces is
public static double round5(double d) {
final double factor = 1e5;
return d > Long.MAX_VALUE / factor || d < -Long.MAX_VALUE / factor ? d :
(long) (d < 0 ? d * factor - 0.5 : d * factor + 0.5) / factor;
}
Note: when you print the double you will still need to specify the number of decimal places you need e.g.
System.out.printf("%.5f", value);

Use java printf-like routine (note it produces platform dependent decimal separators):
String.format("%.5f", a)

Related

Best method to round a double in Java 12/13? [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;

Regarding rounding off a value to certain decimal point

I was going through the class decimal format as I was trying format a decimal number in Java upto 2 decimal places or 3 decimal places.
I come up with this solution as shown below but please also let me know are there any other alternative that java provides us to achieve the same thing..!!
import java.text.DecimalFormat;
public class DecimalFormatExample {
public static void main(String args[]) {
//formatting numbers upto 2 decimal places in Java
DecimalFormat df = new DecimalFormat("#,###,##0.00");
System.out.println(df.format(364565.14));
System.out.println(df.format(364565.1454));
//formatting numbers upto 3 decimal places in Java
df = new DecimalFormat("#,###,##0.000");
System.out.println(df.format(364565.14));
System.out.println(df.format(364565.1454));
}
}
Output:
364,565.14
364,565.15
364,565.140
364,565.145
Please advise what are other alternatives that java provide us to achieve the same thing..!!
If you are bothered by re-defining your DecimalFormat, or if you suspect you'll be needing to do redefine many times, you could also do inline formatting with String.format(). Check the syntax for Formatter especially the Numeric sub-title.
Here is an alternative to round off...
double a = 123.564;
double roundOff = Math.round(a * 10.0) / 10.0;
System.out.println(roundOff);
roundOff = Math.round(a * 100.0) / 100.0;
System.out.println(roundOff);
The output is
123.6
123.56
Number of 0s while multiplying and dividing decides the rounding off.
Here is one method.
float round(float value, int roundUpTo){
float x=(float) Math.pow(10,roundUpTo);
value = value*x; // here you will guard your decimal points from loosing
value = Math.round(value) ; //this returns nearest int value
return (float) value/p;
}

How to get the numbers after the decimal point? (java) [duplicate]

This question already has answers here:
How do I get whole and fractional parts from double in JSP/Java?
(18 answers)
Closed 9 years ago.
double d = 4.321562;
Is there an easy way to extract the 0.321562 on it's own from d? I tried looking in the math class but no luck. If this can be done without converting to string or casting to anything else, even better.
Well, you can use:
double x = d - Math.floor(d);
Note that due to the way that binary floating point works, that won't give you exactly 0.321562, as the original value isn't exactly 4.321562. If you're really interested in exact digits, you should use BigDecimal instead.
Another way to get the fraction without using Math is to cast to a long.
double x = d - (long) d;
When you print a double the toString will perform a small amount of rounding so you don't see any rounding error. However, when you remove the integer part, the rounding is no longer enough and the rounding error becomes obvious.
The way around this is to do the rounding yourself or use BigDecimal which allows you to control the rounding.
double d = 4.321562;
System.out.println("Double value from toString " + d);
System.out.println("Exact representation " + new BigDecimal(d));
double x = d - (long) d;
System.out.println("Fraction from toString " + x);
System.out.println("Exact value of fraction " + new BigDecimal(x));
System.out.printf("Rounded to 6 places %.6f%n", x);
double x2 = Math.round(x * 1e9) / 1e9;
System.out.println("After rounding to 9 places toString " + x2);
System.out.println("After rounding to 9 places, exact value " + new BigDecimal(x2));
prints
Double value from toString 4.321562
Exact representation 4.321562000000000125510268844664096832275390625
Fraction from toString 0.3215620000000001
Exact value of fraction 0.321562000000000125510268844664096832275390625
Rounded to 6 places 0.321562
After rounding to 9 places toString 0.321562
After rounding to 9 places, exact value 0.32156200000000001448796638214844278991222381591796875
NOTE: double has limited precision and you can see representation issue creep in if you don't use appropriate rounding. This can happen in any calculation you use with double esp numbers which are not an exact sum of powers of 2.
Use modulo:
double d = 3.123 % 1;
assertEquals(0.123, d,0.000001);

How to save decimal in java

Having the following code in Java:
double operation = 890 / 1440;
System.out.println(operation);
Result:
0.0
What I want is to save the first 4 decimal digits of this operation (0.6180). Do you know how can I do it?
Initialize your variable with an expression that evaluates to a double rather than an int:
double operation = 890.0 / 1440.0;
Otherwise the expression is done using integer arithmetic (which ends up truncating the result). That truncated result then gets converted to a double.
You can use the double literal d - otherwise your numbers are considered of type int:
double operation = 890d / 1440d;
Then you can use a NumberFormat to specify the number of digits.
For example:
NumberFormat format = new DecimalFormat("#.####");
System.out.println(format.format(operation));
You can also do something like this:
double result = (double) 890 / 1400;
which prints the following:
0.6180555555555556
You can check how to round up the number here
This is done using BigDecimal
import java.math.BigDecimal;
import java.math.RoundingMode;
public class DecimalTest {
/**
* #param args
*/
public static void main(String[] args) {
double operation = 890.0 / 1440.0;
BigDecimal big = new BigDecimal(operation);
big = big.setScale(4, RoundingMode.HALF_UP);
double d2 = big.doubleValue();
System.out.println(String.format("operation : %s", operation));
System.out.println(String.format("scaled : %s", d2));
}
}
Output
operation : 0.6180555555555556
scaled : 0.6181
BigDecimal, although very clumsy to work with, gives some formatting options:
BigDecimal first = new BigDecimal(890);
BigDecimal second = new BigDecimal(1440);
System.out.println(first.divide(second, new MathContext(4, RoundingMode.HALF_EVEN)));
double operation = 890.0 / 1440;
System.out.printf(".4f\n", operation);
If you really want to round to the first 4 fractional digits you can also use integer arithmetic by first multiplying the first number so its digits are shifted the right amount f places to the left:
long fractionalPart = 10000L * 890L / 1440L;
I'm using long here to avoid any overflows in case the temporary result does not fit in 32 bits.

Round a double to 2 decimal places [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;

Categories