Generating a lognormal distribution from an array in Java - java

I didn't find any help on the subject so I'm posting a new question about it. I have a variable containing three values {min, average, standard dev.}. How do I generate a lognormal distribution of this array that would randomly give me a value of the time from the lognormal distribution. Also If I would run it 1000 times I would want to randomly get a value of the time from the lognormal distribution each of the 1000 times. How would I write this in java code? Also I guess running it 1000 times would give me an average of the average in the array?

First, generate standard normal values and convert them to a normal distribution with given parameters. Finally, raise to exponential to get log-normal distribution with given mean and std dev.
Random rng = new Random(0);
double[] logNormalValues = new double[1000];
for (int i = 0; i < logNormalValues.length; i++) {
double stdNormal = rng.nextGaussian();
double normalValue = stdDev * stdNormal + mean;
logNormalValues[i] = Math.exp(normalValue);
}

or this
public static double LogNormal(double mean, double stddev) {
Random randGen = new Random();
double varx = Math.pow(stddev, 2);
double ess = Math.log(1.0 + (varx/Math.pow(mean,2)));
double mu = Math.log(mean) - (0.5*Math.pow(ess, 2));
return Math.pow(2.71828, (mu+(ess*randGen.nextGaussian() ) ) );
}

you can also get a built in function here. in your above example, you won't actually end up with the stddev and mean noted -- they change when you exp() the values.
https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/org/apache/commons/math3/distribution/LogNormalDistribution.html

Related

Why does my code which uses the Ramanujan formula for calculating the value of pi not produce correct values?

package ValueOfPi;
import java.math.*;
import java.util.Scanner;
public class RamanujanAlgorithm {
public static void main(String[] args) {
double constant = 0.0002885855652;
Scanner sc = new Scanner(System.in);
System.out.println("Enter limit of summation : ");
int limit = sc.nextInt();
BigDecimal pireci = new BigDecimal("0.00");
for(int n = 0; n<=limit;n++) {
BigDecimal summation = new BigDecimal((factorial(4*n)/Math.pow(factorial(n), 4))*
(26390*n + 1103)/Math.pow(396, 4*n));
pireci = pireci.add(summation);
}
pireci = pireci.multiply(BigDecimal.valueOf(constant));
BigDecimal pi = BigDecimal.ONE.divide(pireci,pireci.scale(),RoundingMode.HALF_UP);
System.out.println(pi);
}
public static long factorial(int num) {
long factorial = 1;
for(int i = 2; i<=num; i++) {
factorial = factorial*i;
}
return factorial;
}
}
SOURCE OF FORMULA -
The Ramanujan Formula I used is -
https://en.wikipedia.org/wiki/Pi#Rapidly_convergent_series
The first formula you see is the one used by me...
EXPLANATION OF MY CODE
In my code, I have first stored the value of root(8)/9801 in the variable named constant.
Then I have taken user input for the upper limit of the summation...
Then the loop works like the Sigma, where everything on the right side of the sigma in the formula is computed and stored in the BigDecimal pireci and at last after coming out of the loop, I have multiplied pireci with the variable constant
The result is stored in pireci.
So, for getting pi, I find the reciprocal of pireci(because the formula gives me value of 1/pi) and print the result
There is also one method called factorial which I have made to compute the factorial in the formula
RESULTS PRODUCED
On putting limit = 1 I get -
3.14159265383525216155408817653305805189369961082170142700979067898169315680169553
On putting limit = 10 I get -
3.141592653835251522017825683538367933441136808152187507749300560259859937277166891211043856677465587830817787411902252466648641215763228301502439410432665788310356378854402610761037687401200267944051297889143892295707008454487636735727641182639754208990826247667192290712119662965838581189023690921554268043065123435639930191440467906529034361442072184293368529887693375871414064191030918467799966026346716917502424050190813
Whereas, the real value of pi is
3.1415926535 8979323846 2643383279 5028841971 6939937510 5820974944 5923078164 0628620899 8628034825 3421170679 8214808651 3282306647 0938446095......
MY QUESTION
You see, after 9 digits the result obtained by my code starts differing with the real value. Why does this happen????
Is it due to the formula or due to my code???
Please help me.
I have also read that the precision increases with increase in the limit of summation. I tried using a larger limit, still its coming out wrong.
And thank you in advance

Java: method for an equation relevant to the Karplus-Strong equation does not return the anticipated result; unclear cause

In Part 1 of a prompt, I am expected to integrate an equation into Java to get the value for a period (T). The equation is as follows: T = FS / (440 * (2 ^(h/12))
NOTE:
FS = sample rate, which is 44100 / 1.
h = halfstep, which is provided by the user.
An example of this equation is: 44100 / (440 * (2 ^(2/12)) = 89.3
The code I wrote is as follows:
public static double getPeriod(int halfstep) {
double T = 100; // TODO: Update this based on note
double FS = 44100 / 1;
double power = Math.pow(2, (halfstep / 12));
double denominator = 440 * (power);
double result = (FS) / (denominator);
T = Math.round(result);
return T;
}
// Equation test.
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("halfstep is: ");
int halfstep = in.nextInt();
double period = getPeriod(halfstep);
System.out.print("Period: " + period + " ");
}
But when I run through this code with h = 2, T = 100.0 instead of the anticipated 89.3 and I am not sure what the issue is. Any thoughts on what's going on?
Because halfStep is an int, when you write
(halfstep / 12)
the calculation is done by taking halfStep / 12 and rounding down to the nearest integer. As a result, if you plug in 2 here, then halfStep / 12 will come back as 0 instead of 1/6. That's messing up the computation and is likely what's giving you the wrong answer.
You have a few options for how to proceed here. One would be to change halfStep to be a double rather than an int. Another would be to rewrite the division as
halfStep / 12.0
which, since 12.0 is a double literal, will perform the division in the way you intend.
One other potential issue - you declare the variable T as 100.0, but never use T anywhere in the calculation and ultimately overwrite it before returning it. I'm not sure whether this is intentional or whether that indicates that one of the formulas is incorrect.
Hope this helps!

How to generate a sequence between two values in java?

The two values that i have are:
firstval=200.000
Secondval=399.999,
I have to generate a numbers such that when the first decimal part should get incremented till 999 for the integral part, next the integral part should be incremented and then decimal part resets to 000 and starts incrementing for the new number . And this happens till 399.
Like
200.001,200.002.....200.999,201.000,201.002....399.998,399.999"
There is a nice way to get required array with Java 8 Stream API
(1) Use double incrementation
double[] sequence = DoubleStream.iterate(200.0, d -> d + 0.001).limit((int) (1 + (399.999 - 200.0) / 0.001)).toArray();
Note, that summing up lots of doubles will likely give some error, for example on my laptop the last number in the sequence is 399.99899999686227
(2) Better way is to generate integer stream and map it to doubles:
double[] sequence = IntStream.range(200000, 400000).mapToDouble( i -> i * 0.001).toArray();
In this case no error from adding multiple doubles will be accumulated
double start = 200.0;
double end = 399.999;
double increment = 0.001;
for (double v = start; v < end + increment / 2; v += increment) {
System.out.printf("%.3f\n", v);
}
Here's another way to do it:
public static void counterGenerator(double start, double end) {
DecimalFormat counterInDecimalFormat = new DecimalFormat("0.000");
String counterInString = counterInDecimalFormat.format(start);
System.out.println(counterInString); // This is the counter in String format.
double counter = Double.parseDouble(counterInString);
if (counter < end)
counterGenerator(start + 0.001, end);
return;
}
In the above example, you have your counter in String format in the variable called counterInString
But you need not worry about the problems associated with incrementing a Double which is actual residing in a String variable. In the code, you can see the incrementing task is being done by a double counter which gets convert back to String by using the DecimalFormat class.
Here keeping your counter as a String helps you to retain the 0s after decimal in numbers like 200.000.
Hope it helps!

How to get greater precision for PI using the Harmonic Series

trying to get back into Java and have decided to tackle PI. So I made this program based on the Harmonic Series:
public static void main(String [] args)
{
double denominator = 1.0;
double tempValue;
double PI = 0.0;
// End point for program
double stopPoint = 1234.5;
for( int i = 1; i < stopPoint; i++ )
{
tempValue = Math.sqrt( (1/(denominator*denominator))/6 );
PI = PI + tempValue;
denominator = denominator + 1.0;
}
System.out.println( "PI = " + PI );
The application prints this:
PI = 3.1417306496998294
So you can see its mildly working. But when I change the stopPoint value any more I'm not getting a change in precision, at all.
For example changing it to 1234.75 gives the same answer - or perhaps print can't display the exact value? If so what is the best way to print out values like these?
Thanks
EDIT
I've added this code as its a change to the code posted above. Some of the changes include the use of Big Decimal and the inclusion of a while loop instead of a for.
import java.math.BigDecimal;
import java.math.MathContext;
public class MyPI
{
final static BigDecimal ONE = new BigDecimal(1);
final static BigDecimal SIX = new BigDecimal(6);
public static void main(String [] args)
{
BigDecimal deno, temp, tempPI;
int start, end;
start = 1;
end = 500000;
temp = new BigDecimal(0);
// Starting denominator point
deno = ONE;
while( start < end )
{
// Without precision and rounding mode, it will try to return a
// never ending number
temp = temp.add( ONE.divide(deno.pow(2),MathContext.DECIMAL64) );
deno = deno.add(ONE);
start = start + 1;
}
tempPI = temp.multiply(SIX);
// Need to convert to double for square root
double PI = Math.sqrt( tempPI.doubleValue() );
System.out.println( "PI: " + PI );
}
}
This produces the following result:
PI: 3.1415907437318054
Thanks all for the help - will probably add a timer to track how long it takes to do this.
I've been using the BigDecimal type instead of the double, but I have hit a bit of a roadblock—the square root.
Don't take the square root of each term. As shown in this example, add the terms of the series, which has the exact sum π2/6. When your loop terminates, multiply by six and then take a single square root.
If you want more precision, you can use Java's BigDecimal.
Use Java BigDecimal instead of Double that has a limited precision.
The BigDecimal class can give you "arbitrary-precision signed decimal numbers", which is what you want in this case, although the instances of BigDecimal are a little more tricky to work with than literals, the class actually works quickly and can be used to do what you need fairly accurately.
Just for your information, though, using the harmonic series to calculate Pi is pretty inefficient, but I understand doing it as a fun program or to learn something new.

Calculating the average traverse time for a graph in millisecond gives an inconceivable output?

I'm making a performance test about search in graphs (between an adjacency list and adjacency matrix) to calculate average traverse time for whole graph in ms.
However, the output gives a number that I havent seen before. Here is the simple algorithm of test.
double startTime;
double endTime;
double processTime;
double totalTime = 0;
double averageTime = 0;
for (int i = 0; i < 100000; i++) {
startTime = System.nanoTime();
search.DFS(5);
endTime = System.nanoTime();
processTime = (endTime - startTime)/1000000;
totalTime = totalTime + processTime;
}
averageTime = totalTime/100000;
System.out.println("PROCESS TIME in AdjacencyMatrix = " + averageTime + " ms");
and the output looks like ;
PROCESS TIME in AdjacencyMatrix = 1.4765902999997995E-4 ms
When I traverse just one time the output gives convenient data like 0.032344 ms.
Even if you use double you still can get precision errors. Basically a floating point number is always a sum of numbers to the power of ten. With that means not all number can be saved precisely. I'm guessing that's where your problem lies.
As a solution: Use long for your variables which is the return type of System.nanoTime(). The number returned by this is always a whole number.
The number is simply written as a floating point number.
1.4765902999997995E-4 = 0.000147659...
So because it's a very small number, the output is in float format to be easier to read.
EDIT: To clarify about floating point number. It's just a way to write numbers that is usually referred to as "scientific notation". This is just a different and convenient way to write very large or very small numbers. In school you might've run into something like:
3,000,000 = 3 * 10^6 = 3E6
1,456,000,000,000 = 1.456 * 10^12 = 1.456E12
So the "E" simply means *10^. If the numbers are small, you use negative numbers after the E, like this:
0,04653 = 4.653 * 10^-2 = 4.653E-2
0,00000134 = 1.34 * 10^-6 = 1.34E-6
0.000000000000000018 = 1.8 * 10^-17 = 1.8E-17
If you want more examples, you can the box in the top right corner of this wikipedia article

Categories

Resources