This question already has answers here:
Is floating point math broken?
(31 answers)
How to round a number to n decimal places in Java
(39 answers)
Closed 10 months ago.
I've used these posts as reference:
How to round a number to n decimal places in Java
round up to 2 decimal places in java? [duplicate]
After reading through the solutions to these question, I'm still having trouble rounding up to the hundredths place.
Here are what I've tried along with their outputs:
BigDecimal
import java.math.BigDecimal;
import java.math.RoundingMode;
public class RaceCarThread extends Thread {
private static boolean raceNow = false;
private int iterations;
private double lapsCompleted;
private boolean crash;
private int nbrOfCrashes;
// Default constructor
public RaceCarThread() {
super();
}
// Constructor for custom name
public RaceCarThread(String name) {
super(name);
raceNow = true;
lapsCompleted = 0;
crash = false;
nbrOfCrashes = 0;
}
public void run() {
while (!(lapsCompleted >= 17)) {
double randomNum = Math.random();
BigDecimal bd = new BigDecimal(randomNum).setScale(2, RoundingMode.HALF_EVEN);
randomNum = bd.doubleValue();
lapsCompleted = lapsCompleted + randomNum;
System.out.println(lapsCompleted);
}
}
}
10.31
10.5
11.13
11.850000000000001
12.810000000000002
13.570000000000002
14.200000000000003
15.080000000000004
15.800000000000004
16.200000000000003
16.790000000000003
17.430000000000003
Math.round(randomNum*100d) / 100d
public class RaceCarThread extends Thread {
private static boolean raceNow = false;
private int iterations;
private double lapsCompleted;
private boolean crash;
private int nbrOfCrashes;
// Default constructor
public RaceCarThread() {
super();
}
// Constructor for custom name
public RaceCarThread(String name) {
super(name);
raceNow = true;
lapsCompleted = 0;
crash = false;
nbrOfCrashes = 0;
}
public void run() {
while (!(lapsCompleted >= 17)) {
double randomNum = Math.random();
lapsCompleted = lapsCompleted + (Math.round(randomNum * 100d) / 100d);
System.out.println(lapsCompleted);
}
}
}
11.020000000000003
11.730000000000004
12.720000000000004
13.430000000000003
13.930000000000003
14.020000000000003
14.300000000000002
15.210000000000003
15.250000000000002
15.500000000000002
16.32
17.080000000000002
I'm unable to use DecimalFormat due to using the number in calculations.
Edit: The System.out.println(lapsCompleted) is just for checking the values and will be removed once I fix the decimals
If you're going to do calculations with your decimal values, you really need to use BigDecimal throughout. Never trust double or float to give accurate answers to calculations involving decimal values.
Also, when you create a BigDecimal from a double, don't use new BigDecimal(yourDouble), because that just puts the floating point error that's already in your double into the BigDecimal. It's generally much better to use BigDecimal.valueOf(yourDouble), which gives you the decimal value with the least number of decimal places that your double is close enough to. That sounds bad, but it's actually good, because you typically get the value that was used to create the double initially.
For example,
System.out.println(new BigDecimal(0.1)); // prints 0.1000000000000000055511151231257827021181583404541015625
System.out.println(BigDecimal.valueOf(0.1)); // prints 0.1
Related
This question already has answers here:
Float and double datatype in Java
(9 answers)
Closed 6 years ago.
Can someone show me an example of example how I could use Double in the following code?
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
int myFirstNumber = (5+10) + (6*8);//Declaring an integer myFirstNumber
int mySecondNumber = 10;
int myThirdNumber = 3;
int myTotal = myFirstNumber + mySecondNumber + myThirdNumber;
System.out.println(myFirstNumber);//prints variable myFirstNumber
System.out.println("myFirstNumber ");//
System.out.println(myTotal);
}
}
Use either float or double (or their boxed counterparts, Float and Double) when you need to deal with non-integer values. The code you posted has no apparent need for that, so it's hard to answer your question. But one possibility would be if you wanted to compute, say, the average of the three numbers:
public class HelloWorld { public static void main(String[] args) {
System.out.println("Hello, World!");
int myFirstNumber = (5+10) + (6*8);//Declaring an integer myFirstNumber
int mySecondNumber = 10;
int myThirdNumber = 3;
int myTotal = myFirstNumber + mySecondNumber + myThirdNumber;
float average = myTotal / 3.0f;
System.out.println(myFirstNumber);//prints variable myFirstNumber
System.out.println("myFirstNumber ");//
System.out.println(myTotal);
System.out.println(average);
}
As to when to use float vs. double (the title of your question), use double when you can tolerate less rounding error than you get with float.
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
int num = (Integer)this.jSpinner1.getValue();
int d = (Integer)this.jSpinner2.getValue();
int val = (num / d);
jTextField1.setText(String.valueOf(val));
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
int num = (Integer)this.jSpinner1.getValue();
int d = (Integer)this.jSpinner2.getValue();
int val1 = (int) ((double)num / (double)d);
jTextField2.setText(String.valueOf(val1));
}
I am creating a program that uses a numerator and denominator the uses buttons to display integer and double value. The program works but it does not show decimals. It usually goes to the closest whole number. Basically what I need is help with getting decimals to show up in the output. http://imgur.com/WdnxgrH
You are explicitly declaring your output variable as int.
Return a double value, or for better precision, a BigDecimal.
Example
BigDecimal output = new BigDecimal(num)
.divide(new BigDecimal(d), BigDecimal.ROUND_HALF_UP);
I got curious about a rounding algorithm, because in CS we had to emulate an HP35 without using the Math library. We didn't include a rounding algorithm in our final build, but I wanted to do it anyway.
public class Round {
public static void main(String[] args) {
/*
* Rounds by using modulus subtraction
*/
double a = 1.123599;
// Should you port this to another method, you can take this as a parameter
int b = 5;
double accuracy = Math.pow(10, -b);
double remainder = a % accuracy;
if (remainder >= 5 * accuracy / 10) // Divide by ten is important because remainder is smaller than accuracy
a += accuracy;
a -= remainder;
/*
* Removes round off error done by modulus
*/
String string = Double.toString(a);
int index = string.indexOf('.') + b;
string = string.substring(0, index);
a = Double.parseDouble(string);
System.out.println(a);
}
}
Is this a good algorithm, or are there any better ones? I don't care about the ones defined in the Java API, I just wanted to know how it was done.
[EDIT]
Here's the code I came up with after looking over EJP's answer
public class Round {
public static void main(String[] args) {
double a = -1.1234599;
int b = 5;
boolean negative = a < 0;
if (negative) a = -a;
String string = Double.toString(a);
char array[] = string.toCharArray();
int index = string.indexOf('.') + b;
int i = index;
int value;
if (Character.getNumericValue(array[index +1]) >= 5) {
for (; i > 0; i--) {
value = Character.getNumericValue(array[i]);
if (value != -1) {
++value;
String temp = Integer.toString(value)
array[i] = temp.charAt(temp.length()-1);
if (value <= 9) break;
}
}
}
string = "";
for (int j=0; j < index + 1 ; j++) {
string += array[j];
}
a = Double.parseDouble(string);
if (negative) a =-a;
System.out.println(a);
}
}
Floating-point numbers don't have decimal places. They have binary places, and the two are not commensurable. Any attempt to modify a floating-point variable to have a specific number of decimal places is doomed to failure.
You have to do the rounding to a specified number of decimal places after conversion to a decimal radix.
There are a different ways to round numbers. The RoundingMode documentation for Java (introduced in 1.5) should give you a brief introduction to the different methods people use.
I know you said you don't have access to the Math functions, but the simplest rounding you can do is:
public static double round(double d)
{
return Math.floor(d + 0.5);
}
If you don't want to use any Math functions, you could try something like this:
public static double round(double d)
{
return (long)(d + 0.5);
}
Those two probably behave differently in some situations (negative numbers?).
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to round a number to n decimal places in Java
I want to set a specified number of decimal digits in a float (or double), with a method in this form
public float decimalDigits(int x, float n){
....
}
for example
->if I have
float n1=36.58529
the line
float n2=decimalDigits(2, n1);
should return
n2=36.59
->if n1 is:
float n1=36.58329
the line
float n2=decimalDigits(2, n1);
should return
n2=36.58
the line
float n2=decimalDigits(1, n2);
should return
n2=36.6
etc
Use this
public float decimalDigits(int decimaldigits, float x){
final NumberFormat numFormat = NumberFormat.getNumberInstance();
numFormat.setMaximumFractionDigits(decimaldigits);
final String resultS = numFormat.format(x);
String parsable=resultS.replace(".", "");
parsable=resultS.replace(",", ".");
float ris=Float.parseFloat(parsable);
return ris;
}
I have added the String replacement to the code to avoid Parsing issue caused by the dot convention (for example 1234.34 becomes 1.234,34 after the formatting causing error in reparsing in float)
If the your is simply a format visualization problem, you could also use the String and doesn't matter that floating point variables don't have decimal places, so this is another valid method:
public String decimalDigits(int decimaldigits, float x){
final NumberFormat numFormat = NumberFormat.getNumberInstance();
numFormat.setMaximumFractionDigits(decimaldigits);
final String resultS = numFormat.format(x);
return resultS;
}
If someone has doubts about validity of this solution, should ask for details or try to compile the code and test it before downvote, thanks. The code is tested and works like a charm.
WARNING
Clearly you have to pass float because the method use Float.parseFloat, if you want to pass a double you have to use a cast to float before pass it in the method, otherwise you have to change all the method primitive and parse from float to double. Double and float are different.
It is impossible for a routine that returns a float or a double to return correctly rounded values such as 36.59 or 36.6 because these values are not representable in binary floating-point. Binary floating-point can only return values that are close, such as 36.60000000000000142108547152020037174224853515625. There is no bit pattern in binary floating-point that represents the value 36.6.
If you want decimal values, you must use a decimal radix, such as DecimalFormat or BigDecimal.
Possible pseudo code is below:
public class test {
/**
* #param args
*/
public static void main(String[] args) {
System.out.println(decimalDigits(10.09872, 4));
}
static double decimalDigits(double value, int n)
{
double decimal = value - ((int) value);
System.out.println(decimal);
double short_decimal = 0;
for(int i = 0; i < n; i++)
{
/* current digit on decimal */
decimal = decimal * 10;
System.out.println(decimal);
short_decimal += (Math.pow(10, n - i - 1) * (int)decimal);
/* find further */
decimal = decimal - (int)decimal;
}
return (int)value + (double)(short_decimal / Math.pow(10, n));
}
}
Is there a Java Library function which can be used to truncate a number to an arbitrary number of decimal places?
For Example.
SomeLibrary.truncate(1.575, 2) = 1.57
Thanks
Try setScale of BigDecimal like so:
public static double round(double d, int decimalPlace) {
BigDecimal bd = new BigDecimal(d);
bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
return bd.doubleValue();
}
Incredible no one brought this up yet, Java API has had DecimalFormat for ages now for this exact purpose.
For most numbers, you won't be able to get an exact representation of xxx.yyyy unless you use a decimal class with guaranteed accuracy, such as BigDecimal.
There's one in commons-math. Check out http://commons.apache.org/math/apidocs/org/apache/commons/math/util/MathUtils.html:
public static double round(double x,
int scale)
It's implemented using BigDecimal, and is overloaded to allow specifying a rounding method, so you can use it to truncate, like this:
org.apache.commons.math.util.MathUtils.round(1.575, 2,
java.math.BigDecimal.ROUND_DOWN);
Update:
In the last version (Math3), this method is in the class Precision.
org.apache.commons.math3.util.Precision.round(double x, int scale, int roundingMethod)
Simply remove the fractional portion
public double trunk(double value){
return value - value % 1;
}
Use this simple function
double truncateDouble(double number, int numDigits) {
double result = number;
String arg = "" + number;
int idx = arg.indexOf('.');
if (idx!=-1) {
if (arg.length() > idx+numDigits) {
arg = arg.substring(0,idx+numDigits+1);
result = Double.parseDouble(arg);
}
}
return result ;
}
I just want to add to ubuntudroid's solution.
I tried it and it wouldn't round down, so I had to add
df.setRoundingMode(RoundingMode.FLOOR);
for it to work.
here is a short implementation which is many times faster than using BigDecimal or Math.pow
private static long TENS[] = new long[19];
static {
TENS[0] = 1;
for (int i = 1; i < TENS.length; i++) TENS[i] = 10 * TENS[i - 1];
}
public static double round(double v, int precision) {
assert precision >= 0 && precision < TENS.length;
double unscaled = v * TENS[precision];
if(unscaled < Long.MIN_VALUE || unscaled > Long.MAX_VALUE)
return v;
long unscaledLong = (long) (unscaled + (v < 0 ? -0.5 : 0.5));
return (double) unscaledLong / TENS[precision];
}
Delete the assert'ions to taste. ;)
Actually, this sort of thing is easy to write:
public static double truncate(double value, int places) {
double multiplier = Math.pow(10, places);
return Math.floor(multiplier * value) / multiplier;
}
Note that it's Math.floor, because Math.round wouldn't be truncating.
Oh, and this returns a double, because that's what most functions in the Math class return (like Math.pow and Math.floor).
Caveat: Doubles suck for accuracy. One of the BigDecimal solutions should be considered first.
To do it 100% reliably, you'd have to pass the argument as string, not as floating-point number. When given as string, the code is easy to write. The reason for this is that
double x = 1.1;
does not mean that x will actually evaluate to 1.1, only to the closest exactly representable number.
created a method to do it.
public double roundDouble(double d, int places) {
return Math.round(d * Math.pow(10, (double) places)) / Math.pow(10, (double)places);
}