I want to convert a double value to int when and only when 2 numbers after the dot are 0.
Example
double x = 25.001
You can use this :
double x = 25.001;
int i = (int) x;
System.out.println(x);//Input
if (x - i <= 0.01) {
x = (int) x;
}
System.out.println(x);//Output
RESULT
Input Output
25.001 25.0
25.011 25.011
If you want to use a second variable you can use :
int y = 0;
if (x - i <= 0.01) {
y = (int) x;
}
Note
But note, in case your input is not correct, you will always get 0, i like the first solution it is good then the second.
if(x-Integer.parseInt(x)>=0.001)
//Convert here
That rounded number you then cannot store in a double, as a double is always an approximation of a real value - of a series of a (negative) power of 2.
So you should go for BigDecimal as many do that want to do financial software.
If you did something like:
double adjustWhenCloseToInt(double x) {
long n = Math.round(x); // Could overflow for large doubles
if (Math.abs(x - n) < 0.01) {
x = n;
}
return x;
}
A simple
x = adjustWhenCloseToInt(x);
System.out.print(x);
Could still print 0.00000001 or such.
The solution there is
System.out.printf("%.2f", x);
Or better use a localized MessageFormat (thousand separators and such).
As floating point always bears rounding errors, I would in general go for BigDecimal, though it is a circumstantial class to use. Take care to use String constructors:
new BigDecimal("3.99");
As they then can maintain a precision of 2.
Related
According to this question, to create a Double number in a given range, you can use:
Random r = new Random();
double randomValue = rangeMin + (rangeMax - rangeMin) * r.nextDouble();
I'm trying to generate a double number in the double domain [Double.MIN_VALUE, Double.MAX_VALUE] using the same code mentioned above:
package test;
import java.util.Random;
public class Main {
public static void main(String[] args) {
double lower = Double.MIN_VALUE;
double upper = Double.MAX_VALUE;
Random rand = new Random();
for (int i = 0; i < 200; i++) {
double a = lower + (upper - lower) * rand.nextDouble();
System.out.println(a);
}
}
}
However, I'm getting just positive numbers even after many iterations:
1.436326007111308E308
2.7068601271148073E307
1.266896721067985E308
8.273233207049513E306
1.3338832492644417E308
8.584898485464862E307
1.260909190772451E308
1.5511066198317899E307
1.2083062753983258E308
2.449979496663398E307
7.333729592027637E307
7.832069948910962E307
8.493365260900201E307
5.158907971928131E307
3.126231202546818E307
1.3576316635349233E308
1.0991793636673692E308
6.991662398870649E307
My question is: How to generate a double number in the double range?
The results are not what you expected, because MIN_VALUE is the smallest possible positive double value. The smallest possible double value is -Double.MAX_VALUE (note the minus sign).
But you can not simply use lower = -Double.MAX_VALUE, because then, the difference will not be representable as a double, and will overflow.
A first idea would be something like
double d = random.nextDouble() * Double.MAX_VALUE;
if (random.nextBoolean()) d = -d;
to cover the full possible range.
EDIT: A (possibly minor) aside: The proposed method should cover the negative double values as well, and should be correct in the sense that each possible value appears either in its positive or in its negative form with equal probability. However, it will not be able to return the value Double.MAX_VALUE (because the value returned by Random#nextDouble() is strictly smaller than 1.0). But based on the implementation of nextDouble, there anyhow may be double values that will never appear in the output.
Double.MIN_VALUE is the smallest positive value that you can represent as a double.
it is not the largest negative number. that would be -Double.MAX_VALUE
As I said in the comment and others have also said, MIN_VALUE is positive. But even if you use -Double.MAX_VALUE, your computation will overflow double precision when computing upper - lower because the result will be two times the maximum double! One way around this is:
val = Random.nextDouble();
return (val < 0.5) ? (-2 * val) * Double.MAX_VALUE : (2 * (val - 0.5)) * Double.MAX_VALUE;
Numbers are being stored in a database (out of my control) as floats/doubles etc.
When I pull them out they are damaged - for example 0.1 will come out (when formatted) as 0.100000001490116119384765625.
Is there a reliable way to recover these numbers?
I have tried new BigDecimal(((Number) o).doubleValue()) and BigDecimal.valueOf(((Number) o).doubleValue()) but these do not work. I still get the damaged result.
I am aware that I could make assumptions on the number of decimal places and round them but this will break for numbers that are deliberately 0.33333333333 for example.
Is there a simple method that will work for most rationals?
I suppose I am asking is there a simple way of finding the most minimal rational number that is within a small delta of a float number?.
you can store the numbers in the database as String and on the retrieval just parseDouble() them. This way the number wont be damaged, it will be same as you store there.
is there a simple way of finding a rational number that is within 0.00001 of a float number?.
This is called rounding.
double d = ((Number) o).doubleValue();
double d2 = Math.round(d * 1e5) / 1e5;
BigDecimal bd = BigDecimal.valueOf(d2);
or you can use BigDecimal to perform the rounding (I avoid using BigDecimal as it is needelessly slow once you know how to use rounding of doubles)
double d = ((Number) o).doubleValue();
BigDecimal bd = BigDecimal.valueOf(d).setScale(5, RoundingMode.HALF_UP);
Note: never use new BigDecimal(double) unless you understand what it does. Most likely BigDecial.valueOf(double) is what you wanted.
Here's the bludgeon way I have done it - I would welcome a more elegant solution.
I chose an implementation of Rational that had a mediant method ready-made for me.
I refactored it to use long instead of int and then added:
// Default delta to apply.
public static final double DELTA = 0.000001;
public static Rational valueOf(double dbl) {
return valueOf(dbl, DELTA);
}
// Create a good rational for the value within the delta supplied.
public static Rational valueOf(double dbl, double delta) {
// Primary checks.
if ( delta <= 0.0 ) {
throw new IllegalArgumentException("Delta must be > 0.0");
}
// Remove the integral part.
long integral = (long) Math.floor(dbl);
dbl -= integral;
// The value we are looking for.
final Rational d = new Rational((long) ((dbl) / delta), (long) (1 / delta));
// Min value = d - delta.
final Rational min = new Rational((long) ((dbl - delta) / delta), (long) (1 / delta));
// Max value = d + delta.
final Rational max = new Rational((long) ((dbl + delta) / delta), (long) (1 / delta));
// Start the fairey sequence.
Rational l = ZERO;
Rational h = ONE;
Rational found = null;
// Keep slicing until we arrive within the delta range.
do {
// Either between min and max -> found it.
if (found == null && min.compareTo(l) <= 0 && max.compareTo(l) >= 0) {
found = l;
}
if (found == null && min.compareTo(h) <= 0 && max.compareTo(h) >= 0) {
found = h;
}
if (found == null) {
// Make the mediant.
Rational m = mediant(l, h);
// Replace either l or h with mediant.
if (m.compareTo(d) < 0) {
l = m;
} else {
h = m;
}
}
} while (found == null);
// Bring back the sign and the integral.
if (integral != 0) {
found = found.plus(new Rational(integral, 1));
}
// That's me.
return found;
}
public BigDecimal toBigDecimal() {
// Do it to just 4 decimal places.
return toBigDecimal(4);
}
public BigDecimal toBigDecimal(int digits) {
// Do it to n decimal places.
return new BigDecimal(num).divide(new BigDecimal(den), digits, RoundingMode.DOWN).stripTrailingZeros();
}
Essentially - the algorithm starts with a range of 0-1. At each iteration I check to see if either end of the range falls between my d-delta - d+delta range. If it does we've found an answer.
If no answer is found we take the mediant of the two limits and replace one of the limits with it. The limit to replace is chosen to ensure the limits surround d at all times.
This is essentially doing a binary-chop search between 0 and 1 to find the first rational that falls within the desired range.
Mathematically I climb down the Stern-Brocot Tree choosing the branch that keeps me enclosing the desired number until I fall into the desired delta.
NB: I have not finished my testing but it certainly finds 1/10 for my input of 0.100000001490116119384765625 and 1/3 for 1.0/3.0 and the classic 355/113 for π.
im trying to program a little java program, that finds null points in a given function f(x).
This is my idea:
I have X1 and X2 (User input) to define an area where to search for the null point. For example -5 and 5.
private static double Naehern(double X, double X2) {
double Y = -1;
double Step = 0.01;
while(Y < -0.00001 || Y > 0.00001) {
X = X + Step;
Y = f(X);
if(X >= X2) {
break;
}
}
return X;
}
static double f(double x) {
return x * x;
}
I am trying to find a Point X, between X1 and X2, where our null point is with an accuracy of about 5. So, in my while() i am starting at X1 and keep checking for X1 while adding +0,01 to it. At some point it should find a null point.
Problems in my current idea:
When starting with -5 for X1 and 5 for X2, the following happens:
X: -4,99
X: -4,98
X: -4,9700000000000000001
How can i fix this by still using doubles?
Secondly i am getting this number at the end of the program: -6.230779781013496E-14. This is the found null point at X = -6.230779781013496E-14. How can I convert this number into something like a normal-readable double with 5 characters after the "."?
a) you can't, unless you use a step width that is exactly representable in binary, like 1/128 instead of 1/100 (which is not).
b) You can use printf("%.5f", ...), though in your case, the output would be just 0.00000.
You can use System.out.printf, String.format or NumberFormat class to format numbers.
Floats and doubles are not exact values. If you want higher precision, there are better ways than float/double. Yes, BigDecimal, I am looking at you.
Hi I'm trying to run a calculation but I can't seem to put it all on one line, I have to split the result into two seperate lines to achieve the desired result (which seems a bit long winded).
Can anyone explain where I'm going wrong?
both x and y are doubles.
Example 1: (incorrect)
y=0.68
x= (Math.round(y* 10))/10;
result x=0
Example 2: (correct)
y=0.68
x= Math.round(y* 10);
x = x/10;
result x=0.7
thanks for your time.
Math.round returns variable of type long (see: Javadoc), which means that the division by 10 is performed on a long variable resulting in another long variable - that's why you lose the precision.
To make it calculate on it as on double and return double - you have to cast the result of Math.round like this:
x= ((double)Math.round(y* 10))/10;
Have you tried to explicitly specify double in your calculation:
x = ((double)Math.round( y * 10.0)) / 10.0;
Math.round returns a long....
It's hard to tell from your snippets, because they don't include variable types, but it's likely to be integer division that's killing you. When you divide two integers x and y, where x < y, you get zero:
int x = 4;
int y = 10;
int z = x/y; // this is zero.
y=0.68
x= (Math.round(y* 10)) <--- Evaluated as int since Math.round returns int /10; <-- integer division
result x=0
y=0.68
x= Math.round(y* 10) <-- x is stored as double
x = x/10; <-- double division
result x=7
I guess it's because Math.round returns either a long or an int, depending on whether y is double or float. an then you have an integer division.
in the second example x is already a double and that's why you have a double division.
When you write:
double x = (Math.round(y* 10))/10;
(Math.round(y* 10)) is a long (= 7), which you divide by 10, that gives another long (= 0). The result is then converted back to a double and stored in x.
In your second snippet:
double x = Math.round(y* 10);
This is equal to 7 and converted into a double. x / 10 is then a double operation that returns 0.7.
I need to cast a double to an int in Java, but the numerical value must always round down. i.e. 99.99999999 -> 99
Casting to an int implicitly drops any decimal. No need to call Math.floor() (assuming positive numbers)
Simply typecast with (int), e.g.:
System.out.println((int)(99.9999)); // Prints 99
This being said, it does have a different behavior from Math.floor which rounds towards negative infinity (#Chris Wong)
To cast a double to an int and have it be rounded to the nearest integer (i.e. unlike the typical (int)(1.8) and (int)(1.2), which will both "round down" towards 0 and return 1), simply add 0.5 to the double that you will typecast to an int.
For example, if we have
double a = 1.2;
double b = 1.8;
Then the following typecasting expressions for x and y and will return the rounded-down values (x = 1 and y = 1):
int x = (int)(a); // This equals (int)(1.2) --> 1
int y = (int)(b); // This equals (int)(1.8) --> 1
But by adding 0.5 to each, we will obtain the rounded-to-closest-integer result that we may desire in some cases (x = 1 and y = 2):
int x = (int)(a + 0.5); // This equals (int)(1.8) --> 1
int y = (int)(b + 0.5); // This equals (int)(2.3) --> 2
As a small note, this method also allows you to control the threshold at which the double is rounded up or down upon (int) typecasting.
(int)(a + 0.8);
to typecast. This will only round up to (int)a + 1 whenever the decimal values are greater than or equal to 0.2. That is, by adding 0.8 to the double immediately before typecasting, 10.15 and 10.03 will be rounded down to 10 upon (int) typecasting, but 10.23 and 10.7 will be rounded up to 11.
(int)99.99999
It will be 99.
Casting a double to an int does not round, it'll discard the fraction part.
Math.floor(n)
where n is a double. This'll actually return a double, it seems, so make sure that you typecast it after.
This works fine int i = (int) dbl;
new Double(99.9999).intValue()
try with this, This is simple
double x= 20.22889909008;
int a = (int) x;
this will return a=20
or try with this:-
Double x = 20.22889909008;
Integer a = x.intValue();
this will return a=20
or try with this:-
double x= 20.22889909008;
System.out.println("===="+(int)x);
this will return ===20
may be these code will help you.
Try using Math.floor.
In this question:
1.Casting double to integer is very easy task.
2.But it's not rounding double value to the nearest decimal. Therefore casting can be done like this:
double d=99.99999999;
int i=(int)d;
System.out.println(i);
and it will print 99, but rounding hasn't been done.
Thus for rounding we can use,
double d=99.99999999;
System.out.println( Math.round(d));
This will print the output of 100.