I know this question is repeated alot, but please have a look at the statement first than mark it already answered :)
For truncating the double values 2 decimal places I use two ways which are mostly mentioned everywhere. They are given below
//this one
DecimalFormat dtime = new DecimalFormat("#.##");
return Double.valueOf(dtime.format(val));
//or the one below
BigDecimal bd = new BigDecimal(val);
BigDecimal rounded = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
return rounded.doubleValue();
The problem is that for both the ways I mostly get correct rounded values in the dataset. But strangely at the same time I get values like 2.00000000000005 or 19.97999999999.
The problem that I dont get is that why only a few values are not rounded of. What could be wrong?
For truncating the double values 2 decimal places I use two ways which are mostly mentioned everywhere.
And they are both wrong, because they are attempting the impossible. There is no such thing as truncating a double to 2 decimal places, because doubles don't have decimal places. They have binary places. See my answer here for proof. If you want decimal places you have to use a decimal radix, i.e. BigDecimal or DecimalFormat.
Issue is that floating point numbers are inherently approximate in nature, given the underlying representation. Therefore you will want to use them in places where approximations are good, and avoid them where approximations are no good (e.g. financials).
The call to rounded.doubleValue() still returns a floating point number and so it is still impacted by the limitations of the representation.
See
http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
for more information.
The following piece of code helped me in restricting the number of decimal places (truncating) for a double value.
public static Double truncate (double valueToTruncate, int numberOfDecimalPlaces) {
if (valueToTruncate > 0) {
return new BigDecimal(String.valueOf(valueToTruncate)).setScale(numberOfDecimalPlaces, BigDecimal.ROUND_FLOOR).doubleValue();
} else {
return new BigDecimal(String.valueOf(valueToTruncate)).setScale(numberOfDecimalPlaces, BigDecimal.ROUND_CEILING).doubleValue();
}
}
Hope this helps someone :)
I'm new to this but keeping everything in front of me I did it this way. Now mind you this is a truncation mathematically, I don't convert to string except in my debugs after each line.
It isn't elegant but seems to work. This is purely a problem solving framework.
Anyway;
import java.util.Scanner;
public class TestConstructs
{
private static double w;
private static int w1;
private static double w2;
private static double w3;
private static int w4;
private static double w5;
private static double w6;
public static void main(String[] args)
{
// TODO Auto-generated method stub
TestConstructs foo = new TestConstructs();
foo.setWage(w);
}
public void setWage(double w)
{
Scanner input = new Scanner(System.in);
System.out.println("Enter Wage: "); //enter something longish like 30987.978654 or w/e
w = input.nextDouble();
w1 = (int)w;
System.out.printf("%d w1\n",w1);
w2 = w - w1;
System.out.printf("%.3f w2\n",w2);
w3 = w2*100;
System.out.printf("%.3f w3\n",w3);
w4 = (int)w3;
System.out.printf("%d w4\n",w4);
w5 = (double)w4;
System.out.printf("%.3f w5\n",w5);
w6 = 0 + w5/100;
System.out.printf("%.3f w6\n",w6);
w = w1 + w6;
System.out.printf("%.3f final value\n",w); //.3 to show zero
input.close();
}
}
What I got at the end
Enter Wage:
30987.978654
30987 w1
0.979 w2
97.865 w3
97 w4
97.000 w5
0.970 w6
30987.970 final value
Related
I am trying to round a large double (larger than ints allow) so it will print without decimal places to the E13 power, but I don't know how.
I've looked into DecimalFormat and casting and String methods to fix it and no answer has been for a number larger than an int can go.
import java.util.*;
import java.text.*;
class Different {
public static void main(String[] args) {
DecimalFormat df = new DecimalFormat("#,#########");
Scanner in = new Scanner(System.in);
while(in.hasNext()) {
double a = in.nextDouble();
double b = in.nextDouble();
double answer = (Math.abs(a - b));
df.format(answer);
System.out.println(answer);
}
in.close();
}
}
I want it to print
2
71293781685339
12345677654320
but get
2.0
7.1293781685339E13
1.234567765432E13
Check the Java API for System.out.printf(). Specifically it is described in the
PrintStream class
double val = 123.4567765432092;
System.out.printf("%3.14f%n", val);
Keep in mind that double values only have 53 bits of accuracy including the integral part and the mantissa. That equates to about 16 digits. Any more than that and you will need to use BigDecimal.
Try out the below code, it will convert double to long.
long answer = Double.valueOf(Math.abs(a - b)).longValue();
System.out.println(answer);
This question already has answers here:
Why not use Double or Float to represent currency?
(16 answers)
Closed 3 years ago.
I'm trying to split a bill and need to calculate how much each person would owe if the bill was split in even amounts. I know one amount will be different than the rest to account for the lost cents.
Assume 3 people try to split a bill for 200. 200 / 3 is 66.6666666667. What I planned on doing was charging the 2 first people 66.67 and the last gets lucky with the 66.66 bill.
At the minute, I have this so far:
private String calculateAmountToPay(String noOfParticipants, String owed) {
double amountOwed = Double.parseDouble(owed);
int noOfMembers = Integer.parseInt(noOfParticipants);
DecimalFormat amountFormat = new DecimalFormat("#.##");
amountFormat.setRoundingMode(RoundingMode.CEILING);
return amountFormat.format((amountOwed/(double)noOfMembers) / 100);
}
But this always will return 66.67. Is there a way that I can get it to only round up if there is a number greater than 2 decimal places, if not, it stays at 66.66 for example?
Maybe I'm approaching this the wrong way. I know currency can be finicky to deal with.
Before even thinking about arithmetic, you need to know that double is not an appropriate data type for use with currency, because it’s imprecise. So, stop using a floating point type (eg double) as the data type for the quantity of dollars and start using a precise type (eg long) as the data type for the quantity of cents.
The steps then to do the calculation would be to immediately convert everything, with rounding, to cents:
double amountOwed = ...;
int noOfMembers = ...;
long centsOwed = Math.round(amountOwed * 100);
long portionCents = Math.round(amountOwed * 100 / noOfMembers);
long errorCents = portionCents * noOfMembers - centsOwed;
Here’s one way to deal with the error:
long lastPortionCents = portionCents - errorCents;
But it’s possible that the error is more than 1 cent, so a better solution would be to spread the error out evenly by subtracting (or adding if the error is negative) 1 cent from the first (or last, or randomly chosen) errorCents diners.
The rest of the solution is then about rending the above, which I leave to the reader.
As a side note, using cents is how banks transmit amounts (at least for EFTPOS anyway).
Regarding basic software design, I would create a separate method that accepts integer cents and people count as its parameters and returns an array of the "split" amounts. Doing this will not only make your code easier to read, but it will compartmentaise the arithmetic operation and thus enable lots of simple tests to more easily be written, so you can know you have all the edge cases that you can think of covered.
You can use BigDecimal with half rounding mode:
private String calculateAmountToPay(String noOfParticipants, String owed) {
double amountOwed = Double.parseDouble(owed);
int noOfMembers = Integer.parseInt(noOfParticipants);
BigDecimal amount= new BigDecimal((amountOwed / (double) noOfMembers) / 100);
return amount.setScale(2, RoundingMode.HALF_UP).toString();
}
You can just do all the computation with basic primitives converting everything to cents (2 decimals precision), and dividing the left over cents over a portion of the members, no need to overcomplicate it with extra sdks/math manipulations. The following is a working example solving this problem entirely, using these suggestions:
public class AmountDivider {
private int totalMembers, luckies, unluckies;
private double totalAmount, amountPerLucky, amountPerUnlucky;
public AmountDivider(int numMembers, double amountOwed) {
totalMembers = numMembers;
totalAmount = amountOwed;
double centsOwed = amountOwed * 100;
int centsPerMember = (int)(centsOwed / totalMembers);
int centsLeft = (int)centsOwed - centsPerMember * totalMembers;
luckies = totalMembers - centsLeft;
amountPerLucky = centsPerMember / 100.0;
unluckies = centsLeft;
amountPerUnlucky = (centsPerMember + 1) / 100.0;
}
public String toString() {
String luckiesStr = String.format("%d lucky persons will pay %.2f", luckies, amountPerLucky);
String unluckiesStr = String.format("%d unlucky persons will pay %.2f", unluckies, amountPerUnlucky);
return String.format("For amount %f divided among %d: \n%s\n%s\n",
totalAmount, totalMembers, luckiesStr, unluckiesStr);
}
public static void main(String[] args) {
System.out.println(new AmountDivider(3, 200));
System.out.println(new AmountDivider(17, 365.99));
}
}
Complete code on GitHub
Hope this helps.
This question already has answers here:
Java: How to set Precision for double value? [duplicate]
(11 answers)
Closed 5 years ago.
I’m working on a project at the java and can’t get a very important method to work
I have tried multiple solutions many from similar questions in stackoverflow none of the answers seems to work for may case
What I need is a simple method that will get a double and no matter what is the value of the double as long as there is more than two digits after the dot it will return the same number with only the first two digits after the dot
For example even if the input is “-3456.679985432333”
The output would be “-3456.67” and not “-3456.68” like other solutions gave me
The closest solution that seems to work was
public static double round (double d) {
d = (double) (Math.floor(d * 100)) / (100);
return d;
}
Yet it did failed when the input was “-0.3355555555555551” the output was “-0.34” and not “-0.33” as expected
I have no idea why did it fail and I’m out of solutions with only a few hours left for this project.
Edit: the fix I found was simple and worked great
public static double round (double d){
if (d>0) return (double) (Math.floor(d*100))/100;
else
{
return (double) (Math.ceil(d*100))/100;
}
}
Anyway thanks for everyone that explained to me what was wrong with my method and I will make sure to try all of your solutions
Explanation
Java is working correct. It's rather that floor returns the first integer that is less than (or equal) to the given value. It does not round towards zero.
For your input -0.335... you first multiply by 100 and receive -33.5.... If you now use floor you correctly receive -34 since its a negative number and -34 is the first integer below 33.5....
Solution
If you want to strip (remove) everything after the decimal you need to use ceil for negative numbers. Or use a method which always rounds towards zero, i.e. the int cast:
public static double round (double d) {
d = (double) ((int) (d * 100)) / (100);
return d;
}
(also see round towards zero in java)
Better alternatives
However there are dedicated, better, methods to achieve what you want. Consider using DecimalFormat (documentation):
DecimalFormat formatter = new DecimalFormat("##.##"); //
formatter.setRoundingMode(RoundingMode.DOWN); // Towards zero
String result = formatter.format(input);
Or any other variant, just search for it, there are plenty of questions like this: How to round a number to n decimal places in Java
Something like this would suffice:
public static double truncate(double input) {
DecimalFormat decimalFormat = new DecimalFormat("##.##");
decimalFormat.setRoundingMode(RoundingMode.DOWN);
String formatResult = decimalFormat.format(input);
return Double.parseDouble(formatResult);
}
returns:
-3456.67
and
-0.33
respectively for both examples provided.
you are able to do this, all you need to do is:
number * 10 or (100),
then convert to a int,
then back to double and / 10 (or 100).
10 = for 1 number after digit,
100 = for 2 (if i remember correctly).
public static double CustomRound(double number, int digits)
{
if (digits < 0)
throw new IllegalArgumentException();
long f = (long)Math.pow(10, digits);
number = number * f;
long rnd = Math.round(number);
return (double)(rnd / f);
}
An alternative approach:
public static double round(double number, int digits)
{
if (digits < 0)
throw new IllegalArgumentException();
BigDecimal bd = new BigDecimal(value);
bd = bd.setScale(digits, RoundingMode.HALF_UP);
return bd.doubleValue();
}
This question already has answers here:
How to round a number to n decimal places in Java
(39 answers)
Closed 7 years ago.
I have read a lot of stackoverflow questions but none seems to be working for me. i am using math.round() to round off.
this is the code:
class round{
public static void main(String args[]){
double a = 123.13698;
double roundOff = Math.round(a*100)/100;
System.out.println(roundOff);
}
}
the output i get is: 123 but i want it to be 123.14. i read that adding *100/100 will help but as you can see i didn't manage to get it to work.
it is absolutely essential for both input and output to be a double.
it would be great great help if you change the line 4 of the code above and post it.
Well this one works...
double roundOff = Math.round(a * 100.0) / 100.0;
Output is
123.14
Or as #Rufein said
double roundOff = (double) Math.round(a * 100) / 100;
this will do it for you as well.
double d = 2.34568;
DecimalFormat f = new DecimalFormat("##.00");
System.out.println(f.format(d));
String roundOffTo2DecPlaces(float val)
{
return String.format("%.2f", val);
}
BigDecimal a = new BigDecimal("123.13698");
BigDecimal roundOff = a.setScale(2, BigDecimal.ROUND_HALF_EVEN);
System.out.println(roundOff);
Go back to your code, and replace 100 by 100.00 and let me know if it works.
However, if you want to be formal, try this:
import java.text.DecimalFormat;
DecimalFormat df=new DecimalFormat("0.00");
String formate = df.format(value);
double finalValue = (Double)df.parse(formate) ;
double roundOff = Math.round(a*100)/100;
should be
double roundOff = Math.round(a*100)/100D;
Adding 'D' to 100 makes it Double literal, thus result produced will have precision
I know this is 2 year old question but as every body faces a problem to round off the values at some point of time.I would like to share a different way which can give us rounded values to any scale by using BigDecimal class .Here we can avoid extra steps which are required to get the final value if we use DecimalFormat("0.00") or using Math.round(a * 100) / 100 .
import java.math.BigDecimal;
public class RoundingNumbers {
public static void main(String args[]){
double number = 123.13698;
int decimalsToConsider = 2;
BigDecimal bigDecimal = new BigDecimal(number);
BigDecimal roundedWithScale = bigDecimal.setScale(2, 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);
}
}
This program would give us below output
Rounded value with setting scale = 123.14
Rounded value with Dividing by one = 123.14
Try :
class round{
public static void main(String args[]){
double a = 123.13698;
double roundOff = Math.round(a*100)/100;
String.format("%.3f", roundOff); //%.3f defines decimal precision you want
System.out.println(roundOff); }}
This is long one but a full proof solution, never fails
Just pass your number to this function as a double, it will return you rounding the decimal value up to the nearest value of 5;
if 4.25, Output 4.25
if 4.20, Output 4.20
if 4.24, Output 4.20
if 4.26, Output 4.30
if you want to round upto 2 decimal places,then use
DecimalFormat df = new DecimalFormat("#.##");
roundToMultipleOfFive(Double.valueOf(df.format(number)));
if up to 3 places, new DecimalFormat("#.###")
if up to n places, new DecimalFormat("#.nTimes #")
public double roundToMultipleOfFive(double x)
{
x=input.nextDouble();
String str=String.valueOf(x);
int pos=0;
for(int i=0;i<str.length();i++)
{
if(str.charAt(i)=='.')
{
pos=i;
break;
}
}
int after=Integer.parseInt(str.substring(pos+1,str.length()));
int Q=after/5;
int R =after%5;
if((Q%2)==0)
{
after=after-R;
}
else
{
if(5-R==5)
{
after=after;
}
else after=after+(5-R);
}
return Double.parseDouble(str.substring(0,pos+1).concat(String.valueOf(after))));
}
seems like you are hit by integer arithmetic: in some languages (int)/(int) will always be evaluated as integer arithmetic.
in order to force floating-point arithmetic, make sure that at least one of the operands is non-integer:
double roundOff = Math.round(a*100)/100.f;
I just modified your code. It works fine in my system. See if this helps
class round{
public static void main(String args[]){
double a = 123.13698;
double roundOff = Math.round(a*100)/100.00;
System.out.println(roundOff);
}
}
public static float roundFloat(float in) {
return ((int)((in*100f)+0.5f))/100f;
}
Should be ok for most cases. You can still changes types if you want to be compliant with doubles for instance.
This question already has answers here:
How to round a number to n decimal places in Java
(39 answers)
Closed 3 years ago.
This is what I did to round a double to 2 decimal places:
amount = roundTwoDecimals(amount);
public double roundTwoDecimals(double d) {
DecimalFormat twoDForm = new DecimalFormat("#.##");
return Double.valueOf(twoDForm.format(d));
}
This works great if the amount = 25.3569 or something like that, but if the amount = 25.00 or the amount = 25.0, then I get 25.0! What I want is both rounding as well as formatting to 2 decimal places.
Just use: (easy as pie)
double number = 651.5176515121351;
number = Math.round(number * 100);
number = number/100;
The output will be 651.52
Are you working with money? Creating a String and then converting it back is pretty loopy.
Use BigDecimal. This has been discussed quite extensively. You should have a Money class and the amount should be a BigDecimal.
Even if you're not working with money, consider BigDecimal.
Use a digit place holder (0), as with '#' trailing/leading zeros show as absent:
DecimalFormat twoDForm = new DecimalFormat("#.00");
Use this
String.format("%.2f", doubleValue) // change 2, according to your requirement.
You can't 'round a double to [any number of] decimal places', because doubles don't have decimal places. You can convert a double to a base-10 String with N decimal places, because base-10 does have decimal places, but when you convert it back you are back in double-land, with binary fractional places.
This is the simplest i could make it but it gets the job done a lot easier than most examples ive seen.
double total = 1.4563;
total = Math.round(total * 100);
System.out.println(total / 100);
The result is 1.46.
You can use org.apache.commons.math.util.MathUtils from apache common
double round = MathUtils.round(double1, 2, BigDecimal.ROUND_HALF_DOWN);
double amount = 25.00;
NumberFormat formatter = new DecimalFormat("#0.00");
System.out.println(formatter.format(amount));
You can use Apache Commons Math:
Precision.round(double x, int scale)
source: http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/Precision.html#round(double,%20int)
Your Money class could be represented as a subclass of Long or having a member representing the money value as a native long. Then when assigning values to your money instantiations, you will always be storing values that are actually REAL money values. You simply output your Money object (via your Money's overridden toString() method) with the appropriate formatting. e.g $1.25 in a Money object's internal representation is 125. You represent the money as cents, or pence or whatever the minimum denomination in the currency you are sealing with is ... then format it on output. No you can NEVER store an 'illegal' money value, like say $1.257.
Starting java 1.8 you can do more with lambda expressions & checks for null. Also, one below can handle Float or Double & variable number of decimal points (including 2 :-)).
public static Double round(Number src, int decimalPlaces) {
return Optional.ofNullable(src)
.map(Number::doubleValue)
.map(BigDecimal::new)
.map(dbl -> dbl.setScale(decimalPlaces, BigDecimal.ROUND_HALF_UP))
.map(BigDecimal::doubleValue)
.orElse(null);
}
You can try this one:
public static String getRoundedValue(Double value, String format) {
DecimalFormat df;
if(format == null)
df = new DecimalFormat("#.00");
else
df = new DecimalFormat(format);
return df.format(value);
}
or
public static double roundDoubleValue(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;
}
DecimalFormat df = new DecimalFormat("###.##");
double total = Double.valueOf(val);
First declare a object of DecimalFormat class. Note the argument inside the DecimalFormat is #.00 which means exactly 2 decimal places of rounding off.
private static DecimalFormat df2 = new DecimalFormat("#.00");
Now, apply the format to your double value:
double input = 32.123456;
System.out.println("double : " + df2.format(input)); // Output: 32.12
Note in case of double input = 32.1;
Then the output would be 32.10 and so on.
If you want the result to two decimal places you can do
// assuming you want to round to Infinity.
double tip = (long) (amount * percent + 0.5) / 100.0;
This result is not precise but Double.toString(double) will correct for this and print one to two decimal places. However as soon as you perform another calculation, you can get a result which will not be implicitly rounded. ;)
Math.round is one answer,
public class Util {
public static Double formatDouble(Double valueToFormat) {
long rounded = Math.round(valueToFormat*100);
return rounded/100.0;
}
}
Test in Spock,Groovy
void "test double format"(){
given:
Double performance = 0.6666666666666666
when:
Double formattedPerformance = Util.formatDouble(performance)
println "######################## formatted ######################### => ${formattedPerformance}"
then:
0.67 == formattedPerformance
}
Presuming the amount could be positive as well as negative, rounding to two decimal places may use the following piece of code snippet.
amount = roundTwoDecimals(amount);
public double roundTwoDecimals(double d) {
if (d < 0)
d -= 0.005;
else if (d > 0)
d += 0.005;
return (double)((long)(d * 100.0))/100);
}
where num is the double number
Integer 2 denotes the number of decimal places that we want to print.
Here we are taking 2 decimal palces
System.out.printf("%.2f",num);
Here is an easy way that guarantee to output the myFixedNumber rounded to two decimal places:
import java.text.DecimalFormat;
public class TwoDecimalPlaces {
static double myFixedNumber = 98765.4321;
public static void main(String[] args) {
System.out.println(new DecimalFormat("0.00").format(myFixedNumber));
}
}
The result is: 98765.43
int i = 180;
int j = 1;
double div= ((double)(j*100)/i);
DecimalFormat df = new DecimalFormat("#.00"); // simple way to format till any deciaml points
System.out.println(div);
System.out.println(df.format(div));
You can use this function.
import org.apache.commons.lang.StringUtils;
public static double roundToDecimals(double number, int c)
{
String rightPad = StringUtils.rightPad("1", c+1, "0");
int decimalPoint = Integer.parseInt(rightPad);
number = Math.round(number * decimalPoint);
return number/decimalPoint;
}