How to make a randomness checker more efficient - java

Hello I'm trying to make a program to check the distribution of random numbers in Java.
The idea of the program is to (using Java) generate many random numbers and then see how many numbers are in each of the following ranges:
0.0 - 0.1
0.1 - 0.2
0.2 - 0.3
...
0.8 - 0.9
0.9 - 1.0
I have managed to do this but I was wondering if there is a more efficient/quicker way to do it.
public class RandomTest
{
//Get value of digit in tenths place of double
public static int getFirstDecimal(double num)
{
return (int) (num * 10);
}
public static void main(String args[])
{
int[] results = new int[10]; //Results array
double x; //Random number holder
int genNum; //Number of random numbers to generate
for(genNum = 0; genNum < 10000; genNum++)
{
x = Math.random();
results[getFirstDecimal(x)]++;
}
for(int i = 0; i < 10; i++)
{
System.out.println(results[i]);
}
}
}

Try this if you really want to shorten the code:
int[] results = new int[10];
IntStream.range(1, 10000).forEach(s -> results[getFirstDecimal(Math.random())]++);
Arrays.stream(results).forEach(System.out::println);
IntStream from 1 to 10000 is just like a for-loop, and for each of those numbers you do the same thing you did, increment value at corresponding index in an array. Then you just print that array, also using streams. Ofcourse you need to keep your getFirstDecimal method, because this code is using this method inside, you could extract code from that method to the stream, but it would look ugly, I think it's better to have a separate method for that.

Related

Adjust list by normalizing in java

When analysing data sets, such as data for human heights or for human weights, a common step is to adjust the data. This adjustment can be done by normalizing to values between 0 and 1, or throwing away outliers.
For this program, adjust the values by dividing all values by the largest value. The input begins with an integer indicating the number of floating-point values that follow. Assume that the list will always contain fewer than 20 floating-point values.
Output each floating-point value with two digits after the decimal point, which can be achieved as follows:
System.out.printf("%.2f", yourValue);
Ex: If the input is:
5 30.0 50.0 10.0 100.0 65.0
the output is:
0.30 0.50 0.10 1.00 0.65
The 5 indicates that there are five floating-point values in the list, namely 30.0, 50.0, 10.0, 100.0, and 65.0. 100.0 is the largest value in the list, so each value is divided by 100.0.
For coding simplicity, follow every output value by a space, including the last one.
This is my code so far:
import java.util.Scanner;
public class LabProgram {
public static void main(String[] args) {
Scanner scnr = new Scanner(System.in);
double numElements;
numElements = scnr.nextDouble();
double[] userList = new double[numElements];
int i;
double maxValue;
for (i = 0; i < userList.length; ++i) {
userList[i] = scnr.nextDouble();
}
maxValue = userList[i];
for (i = 0; i < userList.length; ++i) {
if (userList[i] > maxValue) {
maxValue = userList[i];
}
}
for (i = 0; i < userList.length; ++i) {
userList[i] = userList[i] / maxValue;
System.out.print(userList[i] + " ");
System.out.printf("%.2f", userList[i]);
}
}
}
I keep getting this output.
LabProgram.java:8: error: incompatible types: possible lossy conversion from double to int
double [] userList = new double [numElements];
^
1 error
I think my variable is messed up. I read through my book and could not find help. Can someone please help me on here. Thank you so much! This has been very stressful for me.
The specific error message is because the index and size of an element must be int. So declare and assign at once: int numElements = scnr.nextInt();
Better way of programming things:
skip manual input (aka Scanner and consorts). Makes you crazy and testing a 100'000'000 times slower
you can integrate the interactive part later, once the method is done. You already know how, your code already shows.
use an explicit method to do your work. Don't throw everything into the main method. This way you can run multiple examples/tests on the method, and you have a better implementation for later.
check for invalid input INSIDE the method that you implement. Once you can rely in such a method, you can keep on using it later on.
you could even move the example numbers to its own test method, so you can run multiple test methods. You will learn about Unit Testing later on.
Example code:
public class LabProgram {
public static void main(final String[] args) {
final double[] initialValues = new double[] { 30.0, 50.0, 10.0, 100.0, 65.0 };
final double[] adjustedValues = normalizeValuesByHighest(initialValues);
System.out.println("Adjusted values:");
for (final double d : adjustedValues) {
System.out.printf("%.2f ", Double.valueOf(d));
}
// expected otuput is 0.30 0.50 0.10 1.00 0.65
System.out.println();
System.out.println("All done.");
}
static public double[] normalizeValuesByHighest(final double[] pInitialValues) {
if (pInitialValues == null) throw new IllegalArgumentException("Invalid double[] given!");
if (pInitialValues.length < 1) throw new IllegalArgumentException("double[] given contains no elements!");
// detect valid max value
double tempMaxValue = -Double.MAX_VALUE;
boolean hasValues = false;
for (final double d : pInitialValues) {
if (Double.isNaN(d)) continue;
tempMaxValue = Math.max(tempMaxValue, d);
hasValues = true;
}
if (!hasValues) throw new IllegalArgumentException("double[] given contains no valid elements, only NaNs!");
// create return array
final double maxValue = tempMaxValue; // final from here on
final double[] ret = new double[pInitialValues.length];
for (int i = 0; i < pInitialValues.length; i++) {
ret[i] = pInitialValues[i] / maxValue; // NaN will stay NaN
}
return ret;
}
}
Output:
Adjusted values:
0,30 0,50 0,10 1,00 0,65
All done.

Optimisation in Java Using Apache Commons Math

I'm trying to minimise a value in Java usingcommons-math. I've had a look at their documentation but I don't really get how to implement it.
Basically, in my code below, I have a Double which has the expected goals in a soccer match and I'd like to optimise the probability value of under 3 goals occurring in a game to 0.5.
import org.apache.commons.math3.distribution.PoissonDistribution;
public class Solver {
public static void main(String[] args) {
final Double expectedGoals = 2.9d;
final PoissonDistribution poissonGoals = new PoissonDistribution(expectedGoals);
Double probabilityUnderThreeGoals = 0d;
for (int score = 0; score < 15; score++) {
final Double probability =
poissonGoals.probability(score);
if (score < 3) {
probabilityUnderThreeGoals = probabilityUnderThreeGoals + probability;
}
}
System.out.println(probabilityUnderThreeGoals); //prints 0.44596319855718064, I want to optimise this to 0.5
}
}
The cumulative probability (<= x) of a Poisson random variable can be calculated by:
In your case, x is 2 and you want to find lambda (the mean) such that this is 0.5. You can type this into WolframAlpha and have it solve it for you. So rather than an optimisation problem, this is just a root-finding problem (though one could argue that optimisation problems are just finding roots.)
You can also do this with Apache Commons Maths, with one of the root finders.
int maximumGoals = 2;
double expectedProbability = 0.5;
UnivariateFunction f = x -> {
double sum = 0;
for (int i = 0; i <= maximumGoals; i++) {
sum += Math.pow(x, i) / CombinatoricsUtils.factorialDouble(i);
}
return sum * Math.exp(-x) - expectedProbability;
};
// the four parameters that "solve" takes are:
// the number of iterations, the function to solve, min and max of the root
// I've put some somewhat sensible values as an example. Feel free to change them
double answer = new BisectionSolver().solve(Integer.MAX_VALUE, f, 0, maximumGoals / expectedProbability);
System.out.println("Solved: " + answer);
System.out.println("Cumulative Probability: " + new PoissonDistribution(answer).cumulativeProbability(maximumGoals));
This prints:
Solved: 2.674060344696045
Cumulative Probability: 0.4999999923623868

Java program to print exponential series for numbers 3 and 5 and limit the result to below 1000

I am new to Java programming and have tried a few problems on Project Euler. I somehow came up with my own problem of printing sequence of exponents of 3 and 5 and limit the result to below 1000. I have researched for 3 days to find the best approach to this problem but I could not find relevant articles. I have come across algorithms on exponential series but those were too advanced for my capability right now.
I would appreciate any help in solving this problem. Please see the code I have tried
public class Exponent {
public static void main (String[] args) {
// Declared integers for base and exponent
int i = 0; /* for base */
int n = 0; /* for exponent */
for (n=1; n<5; n++) {
for (i=1; i<=5; i++) {
if (i%3 == 0 || i%5 == 0) {
System.out.println(Math.pow(i,n));
}
}
}
}
}
This code prints out the following result:
3.0
5.0
9.0
25.0
27.0
125.0
81.0
625.0
My problem is that it is very apparent that I am forcing the exponent to print below 1000 by limiting the base and exponent value inside the loop
for (n=1; n<5; n++) //because n<=5 would print result for 5 power 5 which is 3125
I would like to somehow limit the result to below 1000 so not sure if this declaration is apt
int result = 1000; // result variable as 1000
Also, I want the code to print the output in alternates of 3 and 5 as shown below. My program prints the output in sequence of 3 and 5 respectively.
Desired output:
3.0
5.0
9.0
27.0
125.0
81.0
625.0
243.0
729.0
And stops there because the next value would exceed 1000.
I also wanted to know if there is any other approach instead of using Math.pow() method because it returns a double instead of an int. I would like to avoid the double value and just print as follows:
Without double:
3
5
9
27
81
125
243
625
729
Without using Math.pow() (and printing in different order ):
int[] bases = { 3, 5 };
long maxval = 1000L;
for (int base : bases) {
long value = base;
do {
System.out.println( value );
value *= base;
} while (value < maxval);
}
First create a double to store the result:
double result = 0;
Then create an infinite while loop which calculates the result using 3 and 5 and breaks out once result is above 1000.
while(true)
{
result = Math.pow(3, n);
if(result > 1000)
{
break;
}
System.out.println(((int)result));
result = Math.pow(5, n);
if(result < 1000)
{
System.out.println((int)result);
}
n++;
}
Since exponents of 3 are smaller than 5 don't break out until the maximum exponent in 3 is hit. Since the break does not occur don't print the 5 unless it is valid.
Also to print the double as an int value just cast it to an int.
EDIT:
If you are really worried about efficiency here is a faster solution:
public void calcExponents(int max)
{
int resultThree = 3;
int resultFive = 5;
while(resultThree < max)
{
System.out.println(resultThree);
if(resultFive < max)
{
System.out.println(resultFive);
}
resultThree *= 3;
resultFive *= 5;
}
}
You could also make the 3 and 5 arguments to take it one step further.
Why not check if the result is bigger than 1000, and just break out of the loop if it is?
if(Math.pow(i,n)>=1000)
break;
Hint:
3.0 = 3^1
5.0 = 5^1
9.0 = 3^2
25.0 = 5^2 // I assume you forgot it
27.0 = 3^3
125.0 = 5^3
81.0 = 3^4
625.0 = 5^4
243.0 = 3^5
729.0 = 3^6
and 3x is always smaller than 5x. So a single loop (for the x part) with two computations in the body of the loop one for 3 and one for 5 should do the job. You just have to use some condition for the less than 1000 part to avoid printing 55 and 56.
You could use a single loop, checking exponents for both 3 and 5 on each iteration, and printing each result that is less than 1000.
You just want to make sure that you break the loop once your 3's exceed 1000.
To print integer values, you can simply cast the result of Math.pow() to an int.
There are many different ways that one could write an algorithm like this. Here's a very simple (untested) example:
public class Exponent {
public static void main (String[] args) {
int i = 1; // or start at 0 if you prefer
// set the max value (could also be parsed from args)
int maxValue = 1000;
// the break condition also increments:
while (Math.pow(3, i++) < maxValue) {
int x3 = (int) Math.pow(3, i);
int x5 = (int) Math.pow(5, i);
if (x3 < maxValue) {
System.out.println(x3);
}
if (x5 < maxValue) {
System.out.println(x5);
}
}
}
}

Check if a number is a double or an int

I am trying to beautify a program by displaying 1.2 if it is 1.2 and 1 if it is 1 problem is I have stored the numbers into the arraylist as doubles. How can I check if a Number is a double or int?
Well, you can use:
if (x == Math.floor(x))
or even:
if (x == (long) x) // Performs truncation in the conversion
If the condition is true, i.e. the body of the if statement executes, then the value is an integer. Otherwise, it's not.
Note that this will view 1.00000000001 as still a double - if these are values which have been computed (and so may just be "very close" to integer values) you may want to add some tolerance. Also note that this will start failing for very large integers, as they can't be exactly represented in double anyway - you may want to consider using BigDecimal instead if you're dealing with a very wide range.
EDIT: There are better ways of approaching this - using DecimalFormat you should be able to get it to only optionally produce the decimal point. For example:
import java.text.*;
public class Test
{
public static void main(String[] args)
{
DecimalFormat df = new DecimalFormat("0.###");
double[] values = { 1.0, 3.5, 123.4567, 10.0 };
for (double value : values)
{
System.out.println(df.format(value));
}
}
}
Output:
1
3.5
123.457
10
Another simple & intuitive solution using the modulus operator (%)
if (x % 1 == 0) // true: it's an integer, false: it's not an integer
I am C# programmer so I tested this in .Net. This should work in Java too (other than the lines that use the Console class to display the output.
class Program
{
static void Main(string[] args)
{
double[] values = { 1.0, 3.5, 123.4567, 10.0, 1.0000000003 };
int num = 0;
for (int i = 0; i < values.Length; i++ )
{
num = (int) values[i];
// compare the difference against a very small number to handle
// issues due floating point processor
if (Math.Abs(values[i] - (double) num) < 0.00000000001)
{
Console.WriteLine(num);
}
else // print as double
{
Console.WriteLine(values[i]);
}
}
Console.Read();
}
}
Alternatively one can use this method too, I found it helpful.
double a = 1.99;
System.out.println(Math.floor(a) == Math.ceil(a));
You can use:
double x=4;
//To check if it is an integer.
return (int)x == x;

Generating N numbers that sum to 1

Given an array of size n I want to generate random probabilities for each index such that Sigma(a[0]..a[n-1])=1
One possible result might be:
0 1 2 3 4
0.15 0.2 0.18 0.22 0.25
Another perfectly legal result can be:
0 1 2 3 4
0.01 0.01 0.96 0.01 0.01
How can I generate these easily and quickly? Answers in any language are fine, Java preferred.
Get n random numbers, calculate their sum and normalize the sum to 1 by dividing each number with the sum.
The task you are trying to accomplish is tantamount to drawing a random point from the N-dimensional unit simplex.
http://en.wikipedia.org/wiki/Simplex#Random_sampling might help you.
A naive solution might go as following:
public static double[] getArray(int n)
{
double a[] = new double[n];
double s = 0.0d;
Random random = new Random();
for (int i = 0; i < n; i++)
{
a [i] = 1.0d - random.nextDouble();
a [i] = -1 * Math.log(a[i]);
s += a[i];
}
for (int i = 0; i < n; i++)
{
a [i] /= s;
}
return a;
}
To draw a point uniformly from the N-dimensional unit simplex, we must take a vector of exponentially distributed random variables, then normalize it by the sum of those variables. To get an exponentially distributed value, we take a negative log of uniformly distributed value.
This is relatively late, but to show the ammendment to #Kobi's simple and straightforward answer given in this paper pointed to by #dreeves which makes the sampling uniform. The method (if I understand it clearly) is to
Generate n-1 distinct values from the range [1, 2, ... , M-1].
Sort the resulting vector
Add 0 and M as the first and last elements of the resulting vector.
Generate a new vector by computing xi - xi-1 where i = 1,2, ... n. That is, the new vector is made up of the differences between consecutive elements of the old vector.
Divide each element of the new vector by M. You have your uniform distribution!
I am curious to know if generating distinct random values and normalizing them to 1 by dividing by their sum will also produce a uniform distribution.
Get n random numbers, calculate their sum and normalize the sum to 1
by dividing each number with the sum.
Expanding on Kobi's answer, here's a Java function that does exactly that.
public static double[] getRandDistArray(int n) {
double randArray[] = new double[n];
double sum = 0;
// Generate n random numbers
for (int i = 0; i < randArray.length; i++) {
randArray[i] = Math.random();
sum += randArray[i];
}
// Normalize sum to 1
for (int i = 0; i < randArray.length; i++) {
randArray[i] /= sum;
}
return randArray;
}
In a test run, getRandDistArray(5) returned the following
[0.1796505603694718, 0.31518724882558813, 0.15226147256596428, 0.30954417535503603, 0.043356542883939767]
If you want to generate values from a normal distribution efficiently, try the Box Muller Transformation.
public static double[] array(int n){
double[] a = new double[n];
double flag = 0;
for(int i=0;i<n;i++){
a[i] = Math.random();
flag += a[i];
}
for(int i=0;i<n;i++) a[i] /= flag;
return a;
}
Here, at first a stores random numbers. And the flag will keep the sum all the numbers generated so that at the next for loop the numbers generated will be divided by the flag, which at the end the array will have random numbers in probability distribution.

Categories