Java : Rounding a decimal value to HALF_EVEN - java

I have been trying to write a java code to Round a value to the below requirement.
If x=63.88 => roundedValue= 64.00;
If x=63.50 => roundedValue= 64.00
If x=63.32 => roundedValue= 63.32
I tried with the different roundingModes like CEILING, DOWN, FLOOR, HALFDOWN.
I also tried Math.round();
But I'm unable to get the expected output.
My input is a string and output is a string.
Please find the code snippet I tried below
BigDecimal value1 = new BigDecimal(input);
value1=value1.setScale(2, RoundingMode.HALF_EVEN);
//float rounded=Math.round(amount);
String finalValue=String.valueOf(value1);
I'm unable to get the desired output. Please let me know how to achieve this?
ps: should i consider using float or BigDecimal??

if(x%1 >= .5)
{ x = Math.round(x) }
else //do nothing
This seems like it would give you the desired output you are looking for. So if you really wanted to you could override or create your own method to call for the rounding

What you want to do with this, is providing your own MathContext to specify the behavior of the rounding you want to perform.
The closest you will get to your current requirements is either: using RoundingMode.HALF_UP or RoundingMode.UNNECESSARY
For that you will have to use BigDecimal anyways, since Double and Float do not expose rounding.

public static void main(String args[]) {
Double d = 63.18;
DecimalFormat df = new DecimalFormat("00.00");
if(d % 1 >= 0.5)
System.out.println(df.format(Math.round(d)));
else
System.out.println(d);
}

As in your post, using BigDecimal is the way to go, if you want to use decimal rounding.
If you want to round up for numbers >= X.5 and avoid rounding for numbers < X.5 then you can use this code:
import java.math.BigDecimal;
import java.math.RoundingMode;
public class Round {
public static void main(String[] args) {
System.out.println(round("63.88"));
System.out.println(round("63.50"));
System.out.println(round("63.32"));
}
private static BigDecimal round(String input) {
BigDecimal value = new BigDecimal(input);
BigDecimal rounded = value.setScale(0, RoundingMode.HALF_UP);
if (rounded.compareTo(value) > 0)
return rounded.setScale(2);
return value;
}
}
The output is:
64.00
64.00
63.32

Related

getting wrong output while using numberFormat.parse("") method in java

I have below piece of code:
I am passing value "55.00000000000000" and getting output as 55.00000000000001.
But when i passed "45.00000000000000" and "65.00000000000000" i get output as 45.0 and 65.0.
Can someone please help me to get correct output as 55.0.
NumberFormat numberFormat = NumberFormat.getPercentInstance(Locale.US);
if (numberFormat instanceof DecimalFormat) {
DecimalFormat df = (DecimalFormat) numberFormat;
df.setNegativePrefix("(");
df.setNegativeSuffix("%)");
}
Number numericValue = numberFormat.parse("55.00000000000000%");
numericValue = new Double(numericValue.doubleValue() * 100);
System.out.println(numericValue);
The problem here is that numericValue is mathematically supposed to be 0.55. However, it will be a Double (because numberFormat.parse() can only return a Long or a Double). And a Double cannot hold the value 0.55 exactly. See this link for a complete explanation of why. The result is that as you do further computations with the inexact value, roundoff errors will occur, which is why the result being printed out is not quite the exact value. (A Double also cannot be exactly 0.45 or 0.65; it just happens that when multiplying by 100, the result rounds to the correct integer.)
When dealing with decimal values such as money or percentages, it's preferable to use BigDecimal. If the NumberFormat is a DecimalFormat, you can set things up so that parse returns a BigDecimal:
if (numberFormat instanceof DecimalFormat) {
DecimalFormat df = (DecimalFormat) numberFormat;
df.setNegativePrefix("(");
df.setNegativeSuffix("%)");
df.setParseBigDecimal(true); // ADD THIS LINE
}
Now, when you use numberFormat.parse(), the Number it returns will be a BigDecimal, which is able to hold the exact value 0.55. Now you have to avoid converting it to a double, which will introduce a roundoff error. Instead, you should say something like
Number numericValue = numberFormat.parse("55.00000000000000%");
if (numericValue instanceof BigDecimal) {
BigDecimal bdNumber = (BigDecimal) numericValue;
// use BigDecimal operations to multiply by 100, then print or format
// or whatever you want to do
} else {
// you're stuck doing things the old way, you might get some
// inaccuracy
numericValue = new Double(numericValue.doubleValue() * 100);
System.out.println(numericValue);
}
use this line of code
System.out.println(String.format("%.1f", numericValue));
Where format method use to format your data.

How to add a very small number and a very large number

I am pretty new to Java. I am learning numerical computation at the moment. How does one add and multiply a very small number and a very large number, say something of order $10^{-20}$ and something of order $10^{20}$ to arbitrary precision.
Take a look at the BigDecimal class. From the Javadoc:
Immutable, arbitrary-precision signed decimal numbers.
and:
The BigDecimal class gives its user complete control over rounding behavior.
For your example:
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
BigDecimal big = new BigDecimal("10e20");
BigDecimal small = new BigDecimal("10e-20");
BigDecimal ans = big.add(small);
System.err.println("Answer: " + ans);
}
}
Running gives the following:
$ java Main
Answer: 1000000000000000000000.00000000000000000010
Try the following (didn't count the zeros). You may find other methods to construct 10^20/10^-20 more suitable.
System.out.println( new BigDecimal("0.0000000000000000000000000000001").add( new BigDecimal
("100000000000000000000000000000000")));

How do I use BigDecimal's setScale to get two digits precision

public class Dummy {
public static void main(String args[]) {
String x = "1.234.567,89 EUR";
String e = " EUR";
List<BigDecimal> totals = new ArrayList<BigDecimal>();
totals.add( new BigDecimal(x.replaceAll(" EUR","").replaceAll("\\.","").replaceAll(",",".")));
System.out.println(totals.get(0).add(new BigDecimal(0.10).setScale(3,0)));
}
}
With current code I get 1234567.991 and setting it to setScale(2,0) I get 1234568.00 what I am looking for is 1234567.99. Any help?
Use
System.out.println(totals.get(0).add(new BigDecimal(0.10)
.setScale(2, BigDecimal.ROUND_HALF_UP)));
Out put
1234567.99
I think there must be an inbuilt Java function for this. But otherwise, you can do it with simple mathematics.
You can multiply the number with 100. And then use ceiling or floor function of Java. And then divide it with 100. You got your desired result.
Do not use
new BigDecimal(0.10)
which is both inprecise and does not give a precision/scale of 2.
But use
new BigDecimal("0.10")
This preserves the scale.
This will give desired output.
If you want to go with double at that time we can use DecimalFormat but in bigdecimal setScale is used.
BigDecimal.valueOf(1234567.991).setScale(2, BigDecimal.ROUND_HALF_UP)
.doubleValue();
OUTPUT
1234567.99

Getting answer of method to two decimal places

I am using the code below to get the answer of a method i created into two decomal places. But when I do this and complile i get an error saying identifier expected. 2 error come up one pointing at the 2 and the other just before. what is my problem?
import java.text.NumberFormat;
NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMaximumFractionDigits(2);
What you've shown is correct, assuming that the lines aren't all together (import statements must be outside of any class). So for instance, this is valid:
import java.text.NumberFormat;
class MyClass {
void someMethod() {
NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMaximumFractionDigits(2);
// ...
}
}
...but those lines together as shown in your question are not.
If that's not it, you said that the error seems to focus on the 2. Sometimes when we see questions like this here on SO, it's because some zero-width or space-like special character has accidentally ended up in the source. So it may be that if you delete that line and retype it, you'll wipe out the offending character. (It's actually surprising how often that comes up.)
You can write a general purpose function as follows:
public static double round(double inputNumber, int fractionDigits, int roundingMode) {
BigDecimal bigDecimal = new BigDecimal(inputNumber);
BigDecimal rounded = bigDecimal.setScale(fractionDigits, roundingMode);
return rounded.doubleValue();
}
Please find below the sample test results:
import java.math.BigDecimal;
public class RoundHelper {
public static void main(String[] args) {
System.out.println(RoundHelper.round(123.98980, 2, BigDecimal.ROUND_HALF_UP));
System.out.println(RoundHelper.round(123.98000, 2, BigDecimal.ROUND_HALF_UP));
System.out.println(RoundHelper.round(123.98000, 2, BigDecimal.ROUND_HALF_UP));
System.out.println(RoundHelper.round(123.55087, 2, BigDecimal.ROUND_HALF_UP));
System.out.println(RoundHelper.round(123.14000, 2, BigDecimal.ROUND_HALF_UP));
}
public static double round(double inputNumber, int fractionDigits, int roundingMode) {
BigDecimal bigDecimal = new BigDecimal(inputNumber);
BigDecimal rounded = bigDecimal.setScale(fractionDigits, roundingMode);
return rounded.doubleValue();
}
}
Output:
123.99
123.98
123.98
123.55
123.14

Removing the .0 from a double

I am trying to display numbers in a string dynamically, so if the number has decimal's display them but if not don"t show the .0
example: display 5.5 as 5.5 and 5.0 as 5
This is what I have so far: (answer is a double)
double temp = answer;
long temp2 = (long) temp;
if (temp == temp2) {
output = String.valueOf(temp2);
System.out.println(output);
this work's fine up to about 1e18 then will error out because of the maximum size of a Long.
So how would I achieve this on bigger numbers like 5.43e86
Use DecimalFormat
double answer = 5.0;
DecimalFormat df = new DecimalFormat("###.#");
System.out.println(df.format(answer));
The DecimalFormat suggestions are the easiest way to handle this. If they aren't sufficient, here's another idea.
If you're starting to hit the maximum values that can be represented by primitives in Java, then you may need to move to BigInteger and BigDecimal.
Try playing around with the BigDecimal.toBigInteger() method coupled with the toString() methods on BigDecimal and BigInteger.
It's not good solution
if you use new DecimalFormat("0.#") you are missing data, for example
PI = 3.14, but after parse you ae geting 3.1
Another solution to use eval%1 ? (int)d : d
this time couse max integer limit , again missing data
my solution is working, but it's not good idea
res = removeLastChars(eval,".0");
private String removeLastChars(double eval, String text){
String res = String.valueOf(eval);
int length = text.length();
if (res.length() > length){
res = res.substring((res.length() - length), res.length()).equals(text)
? res.substring(0, (res.length() - length)) : res;
}
return res;
}
Look at
http://download.oracle.com/javase/6/docs/api/java/text/DecimalFormat.html
you would want just DecimalFormat("0.0")

Categories