Generating decimal random numbers in Java in a specific range? - java

How can I generate a random whole decimal number between two specified variables in java,
e.g. x = -1 and y = 1 would output any of -1.0, -0.9, -0.8, -0.7,….., 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.9, 1.0?
Note: it should include 1 and -1 ([-1,1]) . And give one decimal number after point.

Random r = new Random();
double random = (r.nextInt(21)-10) / 10.0;
Will give you a random number between [-1, 1] with stepsize 0.1.
And the universal method:
double myRandom(double min, double max) {
Random r = new Random();
return (r.nextInt((int)((max-min)*10+1))+min*10) / 10.0;
}
will return doubles with step size 0.1 between [min, max].

If you just want between -1 and 1, inclusive, in .1 increments, then:
Random rand = new Random();
float result = (rand.nextInt(21) - 10) / 10.0;

Related

Round double to number in interval, defining by step

I have some abstract double interval, defining by step f.e.:
0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0 - where interval == 0.1
0.0, 0.25, 0.5, 0.75, 1.0 - where interval == 0.25
0.0, 0.5, 1.0 - where interval == 0.5
Does Java have some instrument to "round" some double to closest number, according to interval? f.e:
0.511111 - to 0.5 in first case
0.599999 - to 0.6 in first case
0.511111 - to 0.5 in second case
0.599999 - to 0.5 in second case
0.711111 - to 0.75 in second case
0.744444 - to 0.5 in third case
0.755555 - to 1.0 in third case
0.92222 - to 1.0 in third case
Java has instruments which can round numbers to n decimal places, see How to round a number to n decimal places in Java. For rounding to any interval you specified, you may have to manually use Math.round.
Formula:
Given an interval r and a double value x to round, a simple formula is:
x_rounded = Math.round(x/r)*r;
Examples:
double x = 0.59999;
double r = 0.25; // Quarters
x = Math.round(x/r)*r;
System.out.println(x); // Result is 0.5
double x = 0.59999;
double r = 0.1; // Tenths
x = Math.round(x/r)*r;
System.out.println(x); // Result is approximately 0.6
double x = 0.31421;
double r = 0.125; // Eighths
x = Math.round(x/r)*r;
System.out.println(x); // Result is exactly 0.375
Proof:
The interval r can be thought as the value of a fractional unit.
When r = 0.25, the fractional unit is a quarter.
The value x/r represents the number of fractional units that make up x.
When x = 0.75, r = 0.25, x/r == 3, because x contains three fractional unit, which is the quarter. x/r represents the number of quarters.
Math.round(x) rounds x to the nearest integral value. Similarly, Math.round(x/r) rounds x/r to the nearest integral multiple of that fraction.
For x = 0.7, r = 0.25, we have x/r = 2.8, representing 2.8 quarters. Math.round(x/r) therefore rounds the value to the nearest quarter, 3 quarters.
Math.round(x/r)*r therefore rounds x to the nearest fractional interval r. The multiplier is needed because r is the value of each fractional unit.
For x = 0.7, r = 0.25, Math.round(x/r) represents 3 quarters. It has to be multiplied by r=0.25 to get the rounded value of x.
Use BigDecimal and setScale() to round.
However it will not work with the 0.25 precision, but you might do a workaround, something like this:
public BigDecimal round( BigDecimal value, BigDecimal precision )
{
return value.divide(precision, BigDecimal.ROUND_HALF_UP)
.round(BigDecimal.ROUND_HALF_UP)
.multiply(precision, BigDecimal.ROUND_HALF_UP);
}

I am trying to calculate sine of an angle without using the Math.sin() in java

I am trying to calculate sine of an angle without using the Math.sin(). I got stuck in it's equation as I keep getting the wrong results
note I have a method that changes the angle from degrees to radians
public static double sin(double x, int precision) {
//this method is simply the sine function
double answer = 1, power = 1;
int n = 2,factorial = 1;
while (n<=precision) {
power = (power * x * x *-1) +1 ;
factorial = (factorial * (n +1))* (n-1);
answer = answer + ((power/factorial ));
n = n + 2;
}
return answer;
}
It looks like you're attempting to calculate the sine of angle given in radians using the Maclaurin series, a special case of Taylor series.
sin(x) = x - x^3/3! + x^5/5! - x^7/7! + ...
Your initial answer is 1 when it should be x. Your initial power is 1 when it should be x also.
double answer = x, power = x;
For some reason you're adding one to the power part of the result when you shouldn't be.
power = (power * x * x * -1);
You'll also need to fix your factorial calculation. Multiply by n + 1 and n, not n + 1 and n - 1.
factorial = (factorial * (n + 1)) * (n);
With these fixes, testing:
for (double angle = 0; angle <= Math.PI; angle += Math.PI / 4)
{
System.out.println("sin(" + angle + ") = " + sin(angle, 10));
}
The results are pretty good considering the limitations of precision for floating point arithmetic.
sin(0.0) = 0.0
sin(0.7853981633974483) = 0.7071067811796194
sin(1.5707963267948966) = 0.999999943741051
sin(2.356194490192345) = 0.7070959900908971
sin(3.141592653589793) = -4.4516023820965686E-4
Note that this will get more inaccurate as the values of x get larger, not just because of the inaccuracy to represent pi, but also because of the floating point calculations for adding and subtracting large values.

Cant get Random to generate number between two numbers

Using this code I have been trying to get a number between them
I am using a double so I can use negative numbers
double minX = plugin.getConfig().getDouble("location.min.x");
double maxX = plugin.getConfig().getDouble("location.max.x");
double randomX = random.nextDouble(maxX-minX) + minX;
But I get a
The method nextDouble() in the type Random is not applicable for the arguments (double)
But if I set them to ints it works perfectly fine.
nextDouble(),...Returns the next pseudorandom, uniformly
distributed double value between 0.0 and 1.0 from this random number
generator's sequence.
So change it to:
double randomX = random.nextDouble()*(maxX - minX) + minX;
The method: Random.nextDouble(), like Random.nextBoolean() and a few other methods of the Random class, does not take any upper bound arguments. A common workaround/solution is the one provided by flakes above, ie:
double randomX = random.nextDouble()*(maxX - minX) + minX;

Android - How to customize rounding value?

Hi i really bad at rounding. i am trying to round up a value to the rounding of my country currency.
The rounding example will be :
1.01 > 1.00
1.02 > 1.00
1.03 > 1.05
1.04 > 1.05
1.06 > 1.05
1.07 > 1.05
1.08 > 1.10
1.09 > 1.10
How can i do this kind of rounding? Thanks a lot .
Looks like you're rounding by 0.05 = 1/20th. So the following works:
public static double roundCurrency( double value ) {
return Math.round(value * 20.0 ) / 20.0;
}
This seems to give you the correct mappings - you may need to tweak it when you decide exactly where the cutoffs are.
public void test() {
double [] tests = new double[] {1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9};
for ( double d : tests) {
System.out.println(" "+d + " -> "+round(d, .05, 0.5));
}
}
double round(double d, double fraction, double bias) {
return Math.floor(d / fraction + bias) * fraction;
}
This prints:
1.01 -> 1.0
1.02 -> 1.0
1.03 -> 1.05
1.04 -> 1.05
1.05 -> 1.05
1.06 -> 1.05
1.07 -> 1.05
1.08 -> 1.1
1.09 -> 1.1
double roundedvalue= Math.round( YourValue* 100.0 ) / 100.0;
double roundedvalue= Math.round( YourValue* 2.0 ) / 2.0;
Math.round lets you round a number to the nearest integer. It looks like you're trying to round to the nearest multiple of 0.5. The general way to solve problems like that is
roundedValue = Math.round (X / M) * M;
to round to the nearest multiple of M. So in your case that would be
roundedValue = Math.round (X / 0.5) * 0.5;
which is the same as
roundedValue = Math.round (X * 2.0) / 2.0;
Similarly, if you wanted to round something to the nearest multiple of, say, 0.01, one of these would work:
roundedValue = Math.round (X / 0.01) * 0.01;
roundedValue = Math.round (X * 100.0) / 100.0;
EDIT: It looks like you've changed your question, so what I said earlier about rounding to the nearest multiple of 0.5 isn't correct any more, and now you're rounding to the nearest multiple of 0.05. Anyway, the general method I've discussed still works.
Take a look at the http://docs.oracle.com/javase/6/docs/api/java/lang/Math.html documentation on the Math Class. It lets you perform operations such as Math.round(double x) and
Math.ceil(double x) and Math.floor(double x) . You can use these in combination with an if else statement such as
double value = 1.6;
String valueToString = Double.toString(value);
String [] numbers = valueToString.split(".");
String decimalNums = numbers[1];
int decimal = Integer.parseInt(decimalNums);
if(decimal > 0 && decimal < 5){
decimal = Math.floor(decimal);
}else if(decimal >= 5 && decimal < 8){
decimal = 5;
}else{
decimal = Math.ceil(decimal);
}
This will only work for values that have one decimal place. But its a start. Hope it helps a little.

Calculating the slope of a series of values

I have 2 arrays of equal length. The following function attempts to calculate the slope using these arrays. It returns the average of the slope between each points. For the following data set, I seem to be getting different values than Excel and Google Docs.
double[] x_values = { 1932, 1936, 1948, 1952, 1956, 1960, 1964, 1968,
1972, 1976, 1980 };
double[] y_values = { 197, 203, 198, 204, 212, 216, 218, 224, 223, 225,
236 };
public static double getSlope(double[] x_values, double[] y_values)
throws Exception {
if (x_values.length != y_values.length)
throw new Exception();
double slope = 0;
for (int i = 0; i < (x_values.length - 1); i++) {
double y_2 = y_values[i + 1];
double y_1 = y_values[i];
double delta_y = y_2 - y_1;
double x_2 = x_values[i + 1];
double x_1 = x_values[i];
double delta_x = x_2 - x_1;
slope += delta_y / delta_x;
}
System.out.println(x_values.length);
return slope / (x_values.length);
}
Output
Google: 0.755
getSlope(): 0.962121212121212
Excel: 0.7501
I bet the other two methods are computing the least-squares fit, whereas you are not.
When I verify this conjecture using R, I too get the slope of about 0.755:
> summary(lm(y~x))
Call:
lm(formula = y ~ x)
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -1.265e+03 1.793e+02 -7.053 5.97e-05 ***
x 7.551e-01 9.155e-02 8.247 1.73e-05 ***
The relevant number is the 7.551e-01. It is also worth noting that the line has an intercept of about -1265.
Here is a picture of the least-squares fit:
As to implementing this in your code, see Compute least squares using java
This function will not help you much, as it does not take into account the breadths of the various line segments. Consider the differences in applying it to the points (0,0), (1000,1000), and (1001, 2000) versus (0,0), (1,1), and (2, 1001). Both cases have successive slopes 1 and 1000, yet they look greatly different.
You need to implement the method of least squares: http://en.wikipedia.org/wiki/Least_squares to find the line that best approximates your data set.
One more piece of advice: never throw a java.lang.Exception. Always choose a more-specific exception, even if you must write the class yourself. People using your code will need to handle java.lang.Exception, which interferes badly with their other code.
Edit: use Apache Commons Math class SimpleRegression if that's an option.
Else, here's a method that calculates slope and also intercept, should yield the same results as excel and apache:
private static double intercept(List<Double> yList, List<Double> xList) {
if (yList.size() != xList.size())
throw new IllegalArgumentException("Number of y and x must be the same");
if (yList.size() < 2)
throw new IllegalArgumentException("Need at least 2 y, x");
double yAvg = average(yList);
double xAvg = average(xList);
double sumNumerator = 0d;
double sumDenominator = 0d;
for (int i = 0; i < yList.size(); i++) {
double y = yList.get(i);
double x = xList.get(i);
double yDiff = y - yAvg;
double xDiff = x - xAvg;
double numerator = xDiff * yDiff;
double denominator = xDiff * xDiff;
sumNumerator += numerator;
sumDenominator += denominator;
}
double slope = sumNumerator / sumDenominator;
double intercept = yAvg - (slope * xAvg);
return intercept;
}
private static double average(Collection<Double> doubles) {
return doubles.stream().collect(Collectors.averagingDouble(d -> d));
}
Sources:
Excel doc for SLOPE
Excel doc for INTERCEPT
You should be dividing by x_values.length - 1 . Number of slopes is pairwise.
Edit : Wiki example in my comments shows how to calculate the alpha and beta which determines the slope of the linear regression line.

Categories