Generate a random number within a range using a poisson distribution - java

I need a Poisson distribution.
Currently I have the following code:
public static int getPoisson(double lambda) {
double l = Math.exp(-lambda);
double p = 1.0;
int k = 0;
do {
k++;
p *= Math.random();
} while (p > l);
return k - 1;
}
I was wondering how I could modify it such that I can generate x number of values all within a defined range i.e., if a = 5, b = 10, and lambda = 6, all values generated will fall within the range of 5 to 10.
Note: I could overload the method, and thus accept range parameters, and call the getPossion method within a loop; discarding anything that doesn't fit this range. However, I would like to check whether there is a mathematically defined means of achieving this and/or whether this approach would be suitable.
EDIT: The means by which I discard 'out of bounds' values:
public static int getPoisson(final double min, final double max, final double lambda) {
int k = 0;
do {
k = getPoisson(lambda);
} while (k < min || k > max);
return k;
}

If you want only get some integers in very small given range with given probability with fixed (or rarely changed) lambda the easiest way is to keep probability tables for each of number and do biased sampling.
Some pseudocode:
public class BoundedSampler {
private final int min;
private final double[] table;
public BoundedSampler(int min, int max, double lambda) {
this.min = min;
this.table = new double[max - min + 1];
double cumulative = 0;
for(int x = min; x <= max; ++x) {
double prob = probability(x, lambda);
table[x - min] = cumulative + prob;
cumulative += prob;
}
for(int i = 0; i < table.length; ++i) {
table[i] /= cumulative;
}
}
public int sample() {
double r = Math.random();
for(int i = 0; i < table.length; ++i) {
if(table[i] <= r) {
return i + min;
}
}
return -1; // impossible: last table value == 1
}
}
Or use alias method to fast value selection.

Related

debug problem in the checking, old wizards cult riddle

I'm trying to solve this riddle in java, about an old man who lives because his cult who gives the old man some of their life, this specific code should work to the rules which are given but one of the checks in the testing is an error.
public class hello {
/** set true to enable debug */
static boolean debug = true;
static long old(int n, int m, int k, int newp) {
int max;
int min;
boolean moreRows;
if (m > n) {
min = n;
max = m;
moreRows = true;
} else {
min = m;
moreRows = false;
max = n;
}
int sum = 0;
int[][] ar2 = new int[(int)m][(int)n];
// square part
for (int i = 0; i < min; i++) {
for (int j = 0; j < i; j++) {
int t = i ^ j;
ar2[i][j] = t - (t >= k ? k : 0);;
sum += 2 * t- (t >= k ? k : 0);;
}
}
for (int i = min; i < max; i++) {
for (int j = 0; j < min; j++) {
int t = i ^ j;
sum += t;
if (moreRows) {
ar2[i][j] = t - (t >= k ? k : 0);
} else {
ar2[j][i] = t;
}
}
}
//retrun time
while(newp<sum && newp>0) {
sum=sum-newp;//wrap it up
}
return sum;
}
}
here is the assert equals test which contains multiple examples:
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
public class HelloTest {
#Test
public void example() {
assertEquals(5, Hello.olde(8, 5, 1, 100));
assertEquals(224, Hello.old(8, 8, 0, 100007));
assertEquals(11925, Hello.old(25, 31, 0, 100007));
assertEquals(4323, Hello.old(5, 45, 3, 1000007));
assertEquals(1586,Hello.old(31, 39, 7, 2345));
assertEquals(808451, Hello.old(545, 435, 342, 1000007));
// You need to run this test very quickly before attempting the actual tests :)
assertEquals(5456283, Hello.old(28827050410L, 35165045587L, 7109602, 13719506));
}
}
i get the following errors which looks like a long to int-
./src/test/java/HelloTest.java:19: error: incompatible types: possible lossy conversion from long to int
assertEquals(5456283, hello.old(28827050410L, 35165045587L, 7109602, 13719506));
^
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
1 error
some more errors from harder examples-
assertEquals(5456283, Hello.old(28827050410L, 35165045587L, 7109602, 13719506));
^
./src/test/java/HelloTest.java:39: error: incompatible types: possible lossy conversion from long to int
long expected = Hello.old(m, n, l, t), actual = Hello.old(m, n, l, t);
debug some errors in one of the assert equals and harder examples, I can't really think what can be changed, I'm sure it's something small so help would be appreciated-Note: t will never be bigger than 2^32 - 1(from the instructions of the question)
thanks
The last test will NOT run on a single machine as long values cannot be used as array length and indexes. This has already been explained in the answer/comments to your previous question.
However, it can be deducted from the task that you do not need to store intermediate data in the array at all, you should just calculate the total.
And even if array is not used it is very likely to take a long time to complete the nested loop with 28_827_050_410 * 35_165_045_587L / 2 iterations. If you had a processor with performance of 100 GFlop/s it should be able to count that in over 160 years.
The calculation of t and sum is incorrect.
It should be:
int t = i ^ j;
if (t >= k) {
t -= k;
}
sum += 2 * t; // or sum += t in the second part.
The last loop seems to be replaceable with simple return sum % newp;
Update:
Function old may be refactored as follows (to get rid of the arrays), though it is still a "naive" solution which would not pass the last test.
static int old(int n, int m, int k, int newp) {
int max;
int min;
if (m > n) {
min = n;
max = m;
} else {
min = m;
max = n;
}
int sum = 0;
// square part
for (int i = 0; i < min; i++) {
for (int j = 0; j < i; j++) {
int t = i ^ j;
if (t >= k) {
t -= k;
sum += 2 * t;
}
}
}
for (int i = min; i < max; i++) {
for (int j = 0; j < min; j++) {
int t = i ^ j;
if (t >= k) {
t -= k;
sum += t;
}
}
}
return sum % newp;
}
Output for the 6 tests:
OK! 5
OK! 224
OK! 11925
OK! 4323
OK! 1586
OK! 808451
According to my knowledge, you cant take more than int in the size of an array but if you don't want to change your long everywhere, you can probably add cast.
long m = 434;
int[] obj = new int[(int) m];
Attempting to access beyond the maximum value allowed through an iterator associated with the array would likely result in one of OutOfMemoryException, IndexOutOfBoundsException or a NoSuchElementException depending on implementation.
This is a very impractical use of memory. If one was to want such a data structure, one should investigate less RAM intensive approaches such as databases, sparse arrays, and the like.

Summing up products from java loop

I am having problems with summing up the products produced from my java loop.
public class ArtificialNeuron {
public ArtificialNeuron(double[] weightings) {
weights = weightings;
inputs = new double[6];
inputs[0] = 1;
}
public void setInput(int index, double newValue) {
inputs[index] = newValue;
}
public int activate(double threshold) {
double x = 0;
for(int i=0; i<inputs.length;i++)
x = inputs[i]*weights[i];
double sum = x+x+x+x+x+x;
if(sum >= threshold) {
return 1;
} else {
return -1;
}
}
}
I ran several Junit test and it always seem to fail on the if else statement. I believe it probably my summation method, but I don't know how I would sum up the products.
Based on your code, I think you wanted to add all of the products together. Instead, you are multiplying the last product by 6 (effectively). It's unclear why you have the temporary x, you can add each product to a default sum of 0. Also, I think a test for sum < threshold is a little easier to read (likewise, always use braces with your loops - it's easier to read and reason about). Like,
public int activate(double threshold) {
double sum = 0;
for (int i = 0; i < inputs.length; i++) {
sum += inputs[i] * weights[i]; // sum = sum + (inputs[i] * weights[i])
}
if (sum < threshold) {
return -1;
}
return 1;
}

Getting the wrong output? My coding is maybe off?

Well, I am doing a practice problem (preparing for midterm) and I was able to get one of the outputs correct. However, I am having troublesome getting the average input. It ends up at 12.0 instead of 6.5
Here's the prompt question:5.
Complete the following Java program by filling in the bodies of functions sum(), avg(), and ord(). A call to sum(n) should return the sum of all the integers from 1 to n, while avg(n) returns the average of the same set of numbers. A call to the boolean function ord(x, y, z) returns true if x < y< z and false otherwise. The Function main() should produce the following output
Output:
6.5 true false
This is my code:
class Problem5 {
// sum(): return 1+2+3+..+n
static int sum(int n) { //this is given
int sum = 0;
for(int i=0; i<n; i++) {
sum += n;
}
return n;
}
// avg(): return average of {1,2,..,n}
static double avg(int n) { // given
double sum = 0;
for (int i=1; i<n; i++) {
sum +=n;
}
return sum / n;
}
//ord(): return true if and only if x<y<z
static boolean ord(double x, double y, double z){ //given
if (x < y && y <z){
return true;
} else {
return false;
}
}
public static void main (String[]args) {
System.out.println(avg(12));
System.out.println(ord(1.2,3.4,5.6));
System.out.println(ord(3.4,1.2,5.6));
}
}
Overall I am having trouble coding/ filling in the code for static int sum(int) and static double avg(int).
This:
for (int i=1; i<n; i++){
Will skip n. (it will loop on 1...n-1). For 12, the sum will be 11*12/2, which you then divide by 12, resulting in 11/2 = 6.5
Fix it like so:
for (int i = 1; i <= n; i++) {
(or replace the whole loop by return (double) (n+1) / 2.0)
For your sum function, there is the same error, plus the return value is not good:
return n;
Should be
return sum;
And the increment should be sum += i;, not n (you want 1+2+3+4..., not 12+12+12+12...)
Again, you can replace the whole loop by return n * (n + 1) / 2
I assume your teacher would expect you to learn about re usability, and since your 2 loops in sum and in avg are identical, you could write:
public static double avg(int n) {
return (double) sum(n) / n;
}
A sum is just the addition of all the numbers in a certain range:
static int sum(int n) {
int total = 0;
for(int i = 1; i <= n; i++) {
total += i;
}
return total;
}
Average is just the sum of the range divided by the amount of numbers:
static double avg(int n) {
return sum(n) / (double) n;
}

Average Random Integers

I am trying to write a program that takes an integer as command-line argument, uses random to print N uniform random values between 0 and 1, and then prints their average value.
I'm not sure what arguments to put in the while loop so that random integers are repeated n times, n being the number from the user indicating the number of integers the random has to generate.
Any help would be appreciated.
enter code here
public class UniformRandomNumbers1 {
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
int i;
double total = 0.0; //(The sum of n, numbers)
for (i = 1; i <= n; i++) {
double rand = Math.random(); //(Random number between 0 & 1)
total += rand; // Increment total by rand
System.out.println(i + " = " + rand); // Prints value of n & corresponding double value
}
double average = total / n; // Calculates average of n numbers
System.out.println("Average = " + average); // Prints average of n numbers, Can i get an up vote? :) plz
}
}
if you just need to execute a loop a specific number of times, I'd use a for loop
The following loop will iterate exactly n times, and It's what I personally use when I need to do something exactly n times.
for(int i=0; i<n; i++)
{
//insert body here
}
int total = 0;
for (int current = 1; current <= n; n++) {
double rand = Math.random();
total += rand;
System.out.println(currentN + "= " + rand);
}
System.out.println("Total = " + total);
under the assumption that your PRNG is behaving correcly you just need this:
main()
{
printf("\n0.5");
exit(0);
}
that's for N sufficiently large... computed in constant time. otherwise use the moving average formula:
http://en.wikipedia.org/wiki/Moving_average
which requires only O(1) memory space instead of the naive O(N) approach
here the cut&paste java code:
public class Rolling {
private int size;
private double total = 0d;
private int index = 0;
private double samples[];
public Rolling(int size) {
this.size = size;
samples = new double[size];
for (int i = 0; i < size; i++) samples[i] = 0d;
}
public void add(double x) {
total -= samples[index];
samples[index] = x;
total += x;
if (++index == size) index = 0; // cheaper than modulus
}
public double getAverage() {
return total / size;
}
}

Not ignoring a value?

import java.util.Scanner;
import java.util.Arrays;
public class Improved {
//I resize the array here so that it only counts inputs from the user
//I want to ignore the 0 input from the user
//I think the error happens here or in my main method
public static double[] resizeArray(double[] numbers, double size) {
double[] result = new double[(int)size];
for (int i = 0; i < Math.min(numbers.length, size); ++i) {
result[i] = numbers[i];
}
return result;
}
//compute average nothing is wrong here
public static double getAverage( double[] numbers) {
double sum = 0;
for (int i = 0; i < numbers.length; ++i)
sum += numbers[i];
double average = sum/numbers.length;
return average;
}
//SD nothing is wrong here
public static double getSD( double[] numbers, double average) {
double sd = 0;
for ( int i = 0; i < numbers.length; ++i)
sd += ((numbers[i] - average)*(numbers[i] - average)/ numbers.length);
double standDev = Math.sqrt(sd);
return standDev;
}
//maximum nothing is wrong here
public static double getMax( double[] numbers) {
double max = numbers[0];
for (int i = 1; i < numbers.length; ++i)
if (numbers[i] > max){
max = numbers[i];
}
return max;
}
//minimum nothing is wrong here
public static double getMin( double[] numbers) {
double min = numbers[0];
for (int i = 1; i < numbers.length; ++i)
if (numbers[i] < min) {
min = numbers[i];
}
return min;
}
//median value nothing is wrong here
public static double getmed( double[] numbers) {
double median;
if (numbers.length % 2 == 0)
median = (((numbers[numbers.length/2 - 1])
+ (numbers[numbers.length/2]))/2);
else
median = numbers[numbers.length/2];
return median;
}
//the problem is in the main method i think or in the call method to resize
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
double[] statArr = new double[99];
double size = 0;
int i = 0;
System.out.println("Type your numbers: ");
double number = input.nextDouble();
//I don't want the zero in the array, I want it to be excluded
while (number != 0){
statArr[i] = number;
i++;
number = input.nextDouble();
++size;
if ( size == statArr.length) {
statArr = resizeArray(statArr, statArr.length * 2);
}
++size;
}
statArr = resizeArray(statArr, size);
java.util.Arrays.sort(statArr);
double average = getAverage(statArr);
System.out.println( "The average is " + getAverage(statArr));
System.out.println( "The standard deviation is " + getSD(statArr, average));
System.out.println( "The maximum is " + getMax(statArr));
System.out.println( "The minimum is " + getMin(statArr));
}
}
// I don't have any concerns with computing the math parts, but I can't seem to make it so my array ignores the 0 that ends the while loop. In other words, I want every number included up until the user enters the number 0. Everything else is right. Thank you very much!
You have ++size twice. This means your resizeArray method won't work correctly:
double[] result = new double[(int)size];
Here you're allocating more than what you actually want. This is why you're getting zeroes in your array. Java arrays are initialized to 0 (in case of numeric primitive types).
As Giodude already commented, I suggest you using List implementations (typically ArrayList) instead of arrays everytime you can.
Also size could be declared as int altogether and avoid that cast (and save some extremely slight memory), you're not using it as a double anywhere.

Categories