Math.random() versus Random.nextInt(int) - java

What is the difference between Math.random() * n and Random.nextInt(n) where n is an integer?

Here is the detailed explanation of why "Random.nextInt(n) is both more efficient and less biased than Math.random() * n" from the Sun forums post that Gili linked to:
Math.random() uses Random.nextDouble() internally.
Random.nextDouble() uses Random.next() twice to generate a double that has approximately uniformly distributed bits in its mantissa, so it is uniformly distributed in the range 0 to 1-(2^-53).
Random.nextInt(n) uses Random.next() less than twice on average- it uses it once, and if the value obtained is above the highest multiple of n below MAX_INT it tries again, otherwise is returns the value modulo n (this prevents the values above the highest multiple of n below MAX_INT skewing the distribution), so returning a value which is uniformly distributed in the range 0 to n-1.
Prior to scaling by 6, the output of Math.random() is one of 2^53 possible values drawn from a uniform distribution.
Scaling by 6 doesn't alter the number of possible values, and casting to an int then forces these values into one of six 'buckets' (0, 1, 2, 3, 4, 5), each bucket corresponding to ranges encompassing either 1501199875790165 or 1501199875790166 of the possible values (as 6 is not a disvisor of 2^53). This means that for a sufficient number of dice rolls (or a die with a sufficiently large number of sides), the die will show itself to be biased towards the larger buckets.
You will be waiting a very long time rolling dice for this effect to show up.
Math.random() also requires about twice the processing and is subject to synchronization.

another important point is that Random.nextInt(n) is repeatable since you can create two Random object with the same seed. This is not possible with Math.random().

According to https://forums.oracle.com/forums/thread.jspa?messageID=6594485&#6594485 Random.nextInt(n) is both more efficient and less biased than Math.random() * n

According to this example Random.nextInt(n) has less predictable output then Math.random() * n. According to [sorted array faster than an unsorted array][1] I think we can say Random.nextInt(n) is hard to predict.
usingRandomClass : time:328 milesecond.
usingMathsRandom : time:187 milesecond.
package javaFuction;
import java.util.Random;
public class RandomFuction
{
static int array[] = new int[9999];
static long sum = 0;
public static void usingMathsRandom() {
for (int i = 0; i < 9999; i++) {
array[i] = (int) (Math.random() * 256);
}
for (int i = 0; i < 9999; i++) {
for (int j = 0; j < 9999; j++) {
if (array[j] >= 128) {
sum += array[j];
}
}
}
}
public static void usingRandomClass() {
Random random = new Random();
for (int i = 0; i < 9999; i++) {
array[i] = random.nextInt(256);
}
for (int i = 0; i < 9999; i++) {
for (int j = 0; j < 9999; j++) {
if (array[j] >= 128) {
sum += array[j];
}
}
}
}
public static void main(String[] args) {
long start = System.currentTimeMillis();
usingRandomClass();
long end = System.currentTimeMillis();
System.out.println("usingRandomClass " + (end - start));
start = System.currentTimeMillis();
usingMathsRandom();
end = System.currentTimeMillis();
System.out.println("usingMathsRandom " + (end - start));
}
}

Related

Solving a matrix equation in Java

I have been trying to implement the given formula in JAVA but i was unsuccessful. Can someone help me find what I am doing wrong?
Do i need to shift the summation index and if so how?
My code:
public final class LinearSystem {
private LinearSystem() {
}
public static int[] solve(int [][]A , int []y) {
int n = A.length;
int[] x = new int[n];
for (int i = 0 ; i < n; i++) {
x[i] = 0;
int sum = 0;
for(int k = i + 1 ; k == n; k++) {
sum += A[i][k]*x[k]; // **java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3**
}
x[i] = 1/A[i][i] * (y[i] - sum);
}
return x;
}
public static void main(String[] args) {
int[][]A = new int[][]{{2,-1,-3},{0,4,-1},{0,0,3}};
int [] y = new int[] {4,-1,23};
System.out.println(Arrays.toString(solve(A,y))); **// awaited result [2, -3, 1]**
}
}
Just trying to collect all my comments under the question into one coherent answer, since there are quite a few different mistakes in your program.
This method of solving linear equations relies on your calculating the components of the answer in reverse order - that is, from bottom to top. That's because each x[i] value depends on the values below it in the vector, but not on the values above it. So your outer loop, where you iterate over the x values needs to start at the biggest index, and work down to the smallest. In other words, instead of being for (int i = 0; i < n; i++), it needs to be for (int i = n - 1; i >= 0; i++).
The inner loop has the wrong stopping condition. With a for loop, the part between the two semicolons is the condition to continue iterating, not the condition to stop. So instead of for(int k = i + 1; k == n; k++), you need for(int k = i + 1; k < n; k++).
You're doing an integer division at the beginning of 1 / A[i][i] * (y[i] - sum);, which means the value is rounded to an integer before carrying on. When you divide 1 by another integer, you always get -1, 0 or 1 because of the rounding, and that makes your answer incorrect. The fix from point 4 below will deal with this.
The formula relies on the mathematical accuracy that comes with working with either floating point types or decimal types. Integers aren't going to be accurate. So you need to change the declarations of some of your variables, as follows.
public static double[] solve(double[][] A, double[] y)
double x[] = new double[n];
double sum = 0.0;
along with the corresponding changes in the main method.
First, you need the second loop to go until k < n, otherwise this throws the ArrayOutOfBounds Exceptions.
Second, you need to calculate your x in reverse order as #Dawood ibn Kareem said.
Also, you probably want x[] to be a double-array to not only get 0-values as result.
I am sorry I don't know much about math side so I couldn't fix it to the right solution but I noticed a few things wrong about your code.
1-You shouldn't initialize your arrays as integer arrays, because you will be doing integer division all over the place. For example 1/A[i][i] will result in 0 even if A[i][i] = 2
2-You shouldn't write k == n, if you do it like this then your for loop will only execute if k equals n, which is impossible for your case.
I think you want to do k < n, which loops from i+1 to the point where k = n - 1
Here is my code:
import java.util.Arrays;
public final class LinearSystem {
private LinearSystem() {
}
public static double[] solve(double [][]A , double []y) {
int n = A.length;
double[] x = new double[n];
for (int i = 0 ; i < n; i++) {
x[i] = 0;
int sum = 0;
for(int k = i + 1 ; k < n; k++) {
sum += A[i][k] * x[k]; // **java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3**
}
x[i] = 1/A[i][i] * (y[i] - sum);
}
return x;
}
public static void main(String[] args) {
double[][]A = new double[][]{{2,-1,-3},{0,4,-1},{0,0,3}};
double [] y = new double[] {4,-1,23};
System.out.println(Arrays.toString(solve(A,y))); // awaited result [2, -3, 1]**
}
}
Remember that arrays are indexed from 0, so the last element is at index n - 1, not n.

Efficiently generate 2^n combinations (/w java)

I'm trying to generate all 2^n as efficiently as possible (and save them to an array), like
0001
0010
0011
etc.
Where n could be up to 15.
Here is my code:
public static void main(String args[]) {
final long startTime = System.nanoTime();
final int N = 15;
int m = (int) Math.pow(2, N) - 1;
int[][] array = new int[m][N];
int arrLength = array.length;
for (int i = 0; i < arrLength; i++) {
String str = String.format("%" + N + "s", Integer.toBinaryString(i + 1)).replace(' ', '0');
for (int j = 0; j < N; j++) {
array[i][j] = Character.getNumericValue(str.charAt(j));
}
}
final long duration = System.nanoTime() - startTime;
double sec = (double) duration / 1000000000.0;
System.out.println(sec);
}
Any suggestion on how i can do this faster?
As of now, my timer says it takes ~0.1 to ~0.12
String processing tends to be slow (typically requires loops and allocations). You can just shift the interesting bit to position 0 instead, then cut off higher bit using bitwise and with 1.
for (int i = 0; i < arrLength; i++) {
for (int j = 0; j < N; j++) {
array[i][j] = (i >> j) & 1;
}
}
p.s. I have left out adding 1 to i, wasn't sure if this was intended in the original code, should be straightforward to add as needed.
My most efficient way would be by not generating them at all, which roughly takes... 0 nanoseconds.
These strings are the textual representation of all integers from 0 to 2^n-1, for which enumeration is no mystery. There is no need to store them (in an array), as the keys would be the same as the indexes.
If you have compelling reasons to process them as strings, you can perform the conversion when required, with you own routine or with toBinaryString.
Depending on your application, f.i. string lookup, another option can be to turn the given string to its integer value. If the goal is to check presence/absence of items in a given combination, binary masks will do an effective job.

in Java, design linear algorithm that finds contiguous subsequence with highest sum

this is the question, and yes it is homework, so I don't necessarily want anyone to "do it" for me; I just need suggestions: Maximum sum: Design a linear algorithm that finds a contiguous subsequence of at most M in a sequence of N long integers that has the highest sum among all such subsequences. Implement your algorithm, and confirm that the order of growth of its running time is linear.
I think that the best way to design this program would be to use nested for loops, but because the algorithm must be linear, I cannot do that. So, I decided to approach the problem by making separate for loops (instead of nested ones).
However, I'm really not sure where to start. The values will range from -99 to 99 (as per the range of my random number generating program).
This is what I have so far (not much):
public class MaxSum {
public static void main(String[] args){
int M = Integer.parseInt(args[0]);
int N = StdIn.readInt();
long[] a = new long[N];
for (int i = 0; i < N; i++) {
a[i] = StdIn.readLong();}}}
if M were a constant, this wouldn't be so difficult. For example, if M==3:
public class MaxSum2 {
public static void main(String[] args){
int N = StdIn.readInt(); //read size for array
long[] a = new long[N]; //create array of size N
for (int i = 0; i < N; i++) { //go through values of array
a[i] = StdIn.readLong();} //read in values and assign them to
//array indices
long p = a[0] + a[1] + a[2]; //start off with first 3 indices
for (int i =0; i<N-4; i++)
{if ((a[i]+a[i+1]+a[1+2])>=p) {p=(a[i]+a[i+1]+a[1+2]);}}
//if sum of values is greater than p, p becomes that sum
for (int i =0; i<N-4; i++) //prints the subsequence that equals p
{if ((a[i]+a[i+1]+a[1+2])==p) {StdOut.println((a[i]+a[i+1]+a[1+2]));}}}}
If I must, I think MaxSum2 will be acceptable for my lab report (sadly, they don't expect much). However, I'd really like to make a general program, one that takes into consideration the possibility that, say, there could be only one positive value for the array, meaning that adding the others to it would only reduce it's value; Or if M were to equal 5, but the highest sum is a subsequence of the length 3, then I would want it to print that smaller subsequence that has the actual maximum sum.
I also think as a novice programmer, this is something I Should learn to do. Oh and although it will probably be acceptable, I don't think I'm supposed to use stacks or queues because we haven't actually covered that in class yet.
Here is my version, adapted from Petar Minchev's code and with an important addition that allows this program to work for an array of numbers with all negative values.
public class MaxSum4 {
public static void main(String[] args)
{Stopwatch banana = new Stopwatch(); //stopwatch object for runtime data.
long sum = 0;
int currentStart = 0;
long bestSum = 0;
int bestStart = 0;
int bestEnd = 0;
int M = Integer.parseInt(args[0]); // read in highest possible length of
//subsequence from command line argument.
int N = StdIn.readInt(); //read in length of array
long[] a = new long[N];
for (int i = 0; i < N; i++) {//read in values from standard input
a[i] = StdIn.readLong();}//and assign those values to array
long negBuff = a[0];
for (int i = 0; i < N; i++) { //go through values of array to find
//largest sum (bestSum)
sum += a[i]; //and updates values. note bestSum, bestStart,
// and bestEnd updated
if (sum > bestSum) { //only when sum>bestSum
bestSum = sum;
bestStart = currentStart;
bestEnd = i; }
if (sum < 0) { //in case sum<0, skip to next iteration, reseting sum=0
sum = 0; //and update currentStart
currentStart = i + 1;
continue; }
if (i - currentStart + 1 == M) { //checks if sequence length becomes equal
//to M.
do { //updates sum and currentStart
sum -= a[currentStart];
currentStart++;
} while ((sum < 0 || a[currentStart] < 0) && (currentStart <= i));
//if sum or a[currentStart]
} //is less than 0 and currentStart<=i,
} //update sum and currentStart again
if(bestSum==0){ //checks to see if bestSum==0, which is the case if
//all values are negative
for (int i=0;i<N;i++){ //goes through values of array
//to find largest value
if (a[i] >= negBuff) {negBuff=a[i];
bestSum=negBuff; bestStart=i; bestEnd=i;}}}
//updates bestSum, bestStart, and bestEnd
StdOut.print("best subsequence is from
a[" + bestStart + "] to a[" + bestEnd + "]: ");
for (int i = bestStart; i<=bestEnd; i++)
{
StdOut.print(a[i]+ " "); //prints sequence
}
StdOut.println();
StdOut.println(banana.elapsedTime());}}//prints elapsed time
also, did this little trace for Petar's code:
trace for a small array
M=2
array: length 5
index value
0 -2
1 2
2 3
3 10
4 1
for the for-loop central to program:
i = 0 sum = 0 + -2 = -2
sum>bestSum? no
sum<0? yes so sum=0, currentStart = 0(i)+1 = 1,
and continue loop with next value of i
i = 1 sum = 0 + 2 = 2
sum>bestSum? yes so bestSum=2 and bestStart=currentStart=1 and bestEnd=1=1
sum<0? no
1(i)-1(currentStart)+1==M? 1-1+1=1 so no
i = 2 sum = 2+3 = 5
sum>bestSum? yes so bestSum=5, bestStart=currentStart=1, and bestEnd=2
sum<0? no
2(i)-1(currentStart)+1=M? 2-1+1=2 so yes:
sum = sum-a[1(curentstart)] =5-2=3. currentStart++=2.
(sum<0 || a[currentStart]<0)? no
i = 3 sum=3+10=13
sum>bestSum? yes so bestSum=13 and bestStart=currentStart=2 and bestEnd=3
sum<0? no
3(i)-2(currentStart)+1=M? 3-2+1=2 so yes:
sum = sum-a[1(curentstart)] =13-3=10. currentStart++=3.
(sum<0 || a[currentStart]<0)? no
i = 4 sum=10+1=11
sum>bestSum? no
sum<0? no
4(i)-3(currentStart)+1==M? yes but changes to sum and currentStart now are
irrelevent as loop terminates
Thanks again! Just wanted to post a final answer and I was slightly proud for catching the all negative thing.
Each element is looked at most twice (one time in the outer loop, and one time in the while loop).
O(2N) = O(N)
Explanation: each element is added to the current sum. When the sum goes below zero, it is reset to zero. When we hit M length sequence, we try to remove elements from the beginning, until the sum is > 0 and there are no negative elements in the beginning of it.
By the way, when all elements are < 0 inside the array, you should take only the largest negative number. This is a special edge case which I haven't written below.
Beware of bugs in the below code - it only illustrates the idea. I haven't run it.
int sum = 0;
int currentStart = 0;
int bestSum = 0;
int bestStart = 0;
int bestEnd = 0;
for (int i = 0; i < N; i++) {
sum += a[i];
if (sum > bestSum) {
bestSum = sum;
bestStart = currentStart;
bestEnd = i;
}
if (sum < 0) {
sum = 0;
currentStart = i + 1;
continue;
}
//Our sequence length has become equal to M
if (i - currentStart + 1 == M) {
do {
sum -= a[currentStart];
currentStart++;
} while ((sum < 0 || a[currentStart] < 0) && (currentStart <= i));
}
}
I think what you are looking for is discussed in detail here
Find the subsequence with largest sum of elements in an array
I have explained 2 different solutions to resolve this problem with O(N) - linear time.

BitSet(JAVA) is throwing outofBoundsException in the implementation of Sieve Of Eratosthenes

Here is my function for the implementation of Sieve Of Eratosthenes,
void solve() throws IOException {
int n = 200000;
ArrayList<Integer> primes = new ArrayList<Integer>();
BitSet bs = new BitSet(n + 1);
for(int i = 0; i <= n + 1; i++)
bs.set(i);
//setting bits at 0 and 1 to 0, since these are not considered as primes
bs.clear(0);
bs.clear(1);
for(int i = 2; i <= n + 1; i++) {
if(bs.get(i)) {
//cross out multiples of i starting from i*i (lesser one would have always been crossed out)
for(int j = i*i; j <= n + 1; j += i)
{
bs.clear(j);
}
primes.add(i); //add this prime to the list
}
}
for(int e : primes)
out.println(e);
}
When I run this I get and arrayOutOfBoundsException during the inner for loop, i.e.
for(int j = i*i; j <= n + 1; j += i)
{
bs.clear(j); //EXCEPTION is raised here
}
Error Message that I am getting is:
Exception in thread "main" java.lang.IndexOutOfBoundsException: bitIndex < 0: -2146737495
at java.util.BitSet.clear(BitSet.java:532)
at ERATOSTHENES.solve(ERATOSTHENES.java:45)
I dont understand where is the problem, if I reduce n to 20000, then my code works fine, but after n = 168000 (approx.), it shows this OutofBoundsException.
Is it something specific to BitSet, some property that I am not getting?
You are initialising (in the worst case) the variable i to be a large number close to 200,000 (specifically a large prime number?). That means j, which is initialised as i * i, will be in excess of 40,000,000,000, which is significantly over the max value of int (approx. 2,147,000,000) That means they will overflow over to negative values, which will definitely be out of range.
To solve the problem in this case, declare your variables to be of type long which is 64-bit and can hold much larger values.
You are getting an integer overflow in this line (i*i is negative):
for(int j = i*i; j <= n + 1; j += i)
Example:
System.out.println(168000 * 168000);
Prints:
-1840771072
Which is negative, so is less than n + 1 and passes cycle condition.
I think it could be because you are using an int and the number is getting too big i.e.
200,000 * 200,000 is a huge number and should probably be a long instead.

finding all prime numbers in a given range

I'm writing this Java program that finds all the prime numbers between a given range. Because I'm dealing with really big numbers my code seems to be not fast enough and gives me a time error. Here is my code, does anyone know to make it faster? Thanks.
import java.util.*;
public class primes2
{
private static Scanner streamReader = new Scanner(System.in);
public static void main(String[] args)
{
int xrange = streamReader.nextInt();
int zrange = streamReader.nextInt();
for (int checks = xrange; checks <= zrange; checks++)
{
boolean[] checkForPrime = Primes(1000000);
if (checkForPrime[checks])
{
System.out.println(checks);
}
}
}
public static boolean[] Primes(int n)
{
boolean[] isPrime = new boolean[n + 1];
if (n >= 2)
isPrime[2] = true;
for (int i = 3; i <= n; i += 2)
isPrime[i] = true;
for (int i = 3, end = sqrt(n); i <= end; i += 2)
{
if (isPrime[i])
{
for (int j = i * 3; j <= n; j += i << 1)
isPrime[j] = false;
}
}
return isPrime;
}
public static int sqrt(int x)
{
int y = 0;
for (int i = 15; i >= 0; i--)
{
y |= 1 << i;
if (y > 46340 || y * y > x)
y ^= 1 << i;
}
return y;
}
}
You'll get an enormous improvement just by changing this:
for (int checks = xrange; checks <= zrange; checks++)
{
boolean[] checkForPrime = Primes(1000000);
to this:
boolean[] checkForPrime = Primes(1000000);
for (int checks = xrange; checks <= zrange; checks++)
{
Your current code regenerates the sieve zrange - xrange + 1 times, but you actually only need to generate it once.
The obvious problem is that you're computing the primes up to 1000000 many time (zrange - xrange times). Another is that you dont need to compute the primes up to 1000000, you just need to check to primes up to zrange, so you're wasting time when zrange < 1000000, and getting a buffer overflow when zrange > 1000000.
You can start your inner loop from i*i, i.e. instead of for (int j = i * 3; j <= n; j += i << 1) you can write for (int j = i * i; j <= n; j += i << 1) for a minor speed-up.
Also, you have to be sure that your zrange is not greater than 1000000.
If xrange is much greater than sqrt(zrange), you can also split your sieve array in two, for an offset sieve scheme. The lower array will span from 2 to sqrt(zrange). The upper one will span from xrange to zrange. As you sieve your lower array, as each new prime becomes identified by it, inside your inner loop, in addition to marking the lower array up to its end also sieve the upper array. You will have to calcuate the starting offset for each prime i, and use the same step of 2*i as you do for the lower half. If your range is wider than a few primes, you will get speed advantage (otherwise just trial division by odds will suffice).
Another thing to try is, if evens > 2 are not primes anyway, why represent them in the array and waste half of the space? You can treat each i as representing an odd number, 2*i+1, thus compressing your array in half.
Last simple trick is to eliminate the multiples of 3 in advance as well, by marking ON not just odds (i.e. coprimes with 2), by { ... i+=2; ...}, but only coprimes with 2 and 3, by { ... i+=2; ... i+=4; ... } instead. Also, when marking OFF multiples of primes > 3, use { ... j+=2*i; ... j+=4i; ...} too. E.g., in 5*5, 5*7, 5*9, 5*11, ... you don't need to mark OFF 5*9, if no multiple of 3 was marked ON in the first place.

Categories

Resources