How to get while loop to work? - java

I'm having trouble getting the while loop to work the way I want it. I've written a method called trapezium (that calculates the area of a trapezium). I need the screen to print the area of the trapezium, then the area of a trapezium with the value of N doubled and then the difference between these two, which it does.
I then need the while loop to keep doubling N, inputting this in the formula, and printing the new difference UNTIL this new difference is less than or equal to a user inputted value called eps. It then needs to print to the screen the area found and the value of N required to do this.
double traparea = trapezium(a, b, N);
System.out.println(traparea + " using the trapezium rule");
double traparea2 = trapezium(a, b, 2 * N);
double difftrap = (traparea2 - traparea);
System.out.println(traparea2);
System.out.println(difftrap);
while (Math.abs(difftrap) < eps) {
N = 2 * N;
traparea2 = trapezium(a, b, N);
difftrap = traparea2 - traparea;
}
System.out.println("The integration from trapezium rule and the value of N are:");
System.out.print(traparea2 + " " + N);

UNTIL this new difference is less than or equal to a user inputted value called eps
while (difftrap>eps) // do the loop as long as the difference is not less than or equal to eps

Related

Problems Generating A Math.random Number, Either 0 or 1

I want a random number, either 0 or 1 and then that will be returned to main() as in my code below.
import java.util.Scanner;
public class Exercise8Lab7 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int numFlips = 0;
int heads = 0;
int tails = 0;
String answer;
System.out.print("Please Enter The Number Of Coin Tosses You Want: ");
numFlips = input.nextInt();
for(int x = 1;x <= numFlips; x++){
if(coinToss() == 1){
answer = "Tails";
tails++;
}
else{
answer = "Heads";
heads++;
}
System.out.print("\nCoin Toss " + x + ": " + answer);
}
System.out.println("\n\n====== Overall Results ======" +
"\nPercentage Of Heads: " + (heads/numFlips)*100 + "\nPercentage Of Tails: " + (tails/numFlips)*100);
}
public static int coinToss(){
double rAsFloat = 1 * (2 + Math.random( ) );
int r = (int)rAsFloat;
return r;
}
}
Many solutions had been suggested to use the util.Random option which I have done and works perfectly but I want to sort out why I can't get this to work. Obviously I want the number to be an int myself so I convert it to an int after the random number has been generated. But no matter what I add or multiply the Math.random() by, it will always all either be Heads or all either be Tails. Never mixed.
Try this) It will generate number 0 or 1
Math.round( Math.random() ) ;
You could use boolean values of 0 or 1 based on value of Math.random() as a double between 0.0 and 1.0 and make the random generator much simpler. And you can get rid completely of the coinToss() method.
if(Math.random() < 0.5) {
answer = "Tails";
tails++;
}
Remove the coin toss method and replace the first conditional with the code above.
Math.random(); by itself will return a value between 0.0 and less than 1.0. If the value is in the lower half, [0.0, 0.5), then it has the same probability of being in the upper half, [0.5, 1.0). Therefore you can set any value in the lower half as true and upper as false.
Wierd that no one is using a modulo division for the random number.
This is the simplest implementation you can get:
Random rand = new Random();
int randomValue = rand.nextInt() % 2;
Math.round(Math.random()) will return either 0.0 and 1.0. Since both these values are well within the limits of int range they can be casted to int.
public static int coinToss(){
return (int)Math.round(Math.random());
}
(int)(Math.random()*2) also works fine in this case
its not working because of the integer math you are using, the call to 2+ Math.Random is pretty much always giving you a answer between 0.0 and 1.0.
so assuming that you recieve 0.25 as your result your maths is as follows
double d = 1* (2 + 0.25); // (result = 2
Then you are checking to see if your result == 1 ( which it never will. )
A better result would be to declare java.util.Random as a class variable and call random.nextBoolean() and simply perform your heads/tails calculation on that.
If you were to continue to use Math.random() and lets say
return Math.random() < 0.5
Your results would be ever so slightly skewed due to the fact that Math.random() cannot return 1.0, due to the fact that the java API specification states:
"Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0."
Math.random() returns a random float in the range [0.0,1.0)--that means the result can be anything from 0 up to but not including 1.0.
Your code
double rAsFloat = 1 * (2 + Math.random( ) );
will take this number in the [0.0,1.0) range; adding 2 to it gives you a number in the [2.0,3.0) range; multiplying it by 1 does nothing useful; then, when you truncate it to an integer, the result is always 2.
To get integers from this kind of random function, you need to figure out how many different integers you could return, then multiply your random number by that. If you want a "0 or 1" answer, your range is 2 different integers, so multiply Math.random() by 2:
double rAsFloat = 2 * Math.random();
This gives you a random number in the range [0.0,2.0), which can then be 0 or 1 when you truncate to an integer with (int). If, instead, you wanted something that returns 1 or 2, for example, you'd just add 1 to it:
double rAsFloat = 1 + 2 * Math.random();
I think you've already figured out that the Random class gives you what you want a lot more easily. I've decided to explain all this anyway, because someday you might work on a legacy system in some old language where you really do need to work with a [0.0,1.0) random value. (OK, maybe that's not too likely any more, but who knows.)
The problem can be translated to boolean generation as follow :
public static byte get0Or1 {
Random random = new Random();
boolean res= random.nextBoolean();
if(res)return 1;
else return 0;
}
Here it the easiest way I found without using java.util.Random.
Blockquote
Scanner input = new Scanner (System.in);
System.out.println("Please enter 0 for heads or 1 for tails");
int integer = input.nextInt();
input.close();
int random = (int) (Math.random() + 0.5);
if (random == integer) {
System.out.println("correct");
}
else {
System.out.println("incorrect");
}
System.out.println(random);
This will take a random double from (0 to .99) and add .5 to make it (.5 to 1.49). It will also cast it to an int, which will make it (0 to 1). The last line is for testing.
for(int i=0;i<100;i++){
System.out.println(((int)(i*Math.random())%2));
}
use mod it will help you!
One more variant
rand.nextInt(2);
As it described in docs it will return random int value between 0 (inclusive) and the specified value (exclusive)

Trapez Method in Java

I found a formula in the Internet for calculating the trapezoid method , it works as it should, but I do not see why should I performed the following lines in the trapez method:
sum = 0.5 * bef + (h * sum);
i= i+ 2
The first iteration performed by the following command in main :
tra[0] = 0.5 * ((b - a) / n) * (function(a) + function(b));
//calculates the first step value
the trapez method for the next iterations:
/**
* calculate the next step with trapez method
* #param a -lower limit
* #param b -upper limit
* #param bef -previous step value
* #param n -number of dividing points
* #return integral area
*/
public static double trapz(double a, double b,double bef, int n)
{
double sum = 0;
double h = ((b - a)/n);
for (int i = 1; i <= n; i = i + 2) {
sum += function(a + (i) * h);
}
sum = 0.5 * bef + (h * sum);
return sum;
}
The function would be used in conjunction with a driver loop that doubles the number of subintervals at each iteration, refining the estimated integral until the difference from one iteration to the next is less than some threshold criterion. It is desirable in such an endeavor to avoid repeating computations that have already been performed, and that's the point of the lines you asked about.
Consider the function values that are needed when applying the trapezoid rule on a given number of subintervals. Now consider the function values needed for splitting each subinterval in half and applying the trapezoid rule to those subintervals. Half (give or take 1) of the function values needed in the latter case are the same ones needed in the former. The code presented simply reuses the previously computed values (0.5 * bef), adding to them only the new values (i = i + 2). It must scale down the previous estimate by a factor of two to account for splitting the subintervals in two.
Note that for the code to be right, it appears that argument n must represent the number of subintervals of the integration region, not the number of dividing points as its documentation claims.

run an entire program a certain number of times via input

So my current code effectively runs the "random walk" problem and then uses the pythagorean theorem to figure out actual distance in units walked but now I need to modify my program so that I can do a certain number of trials of said walk and then calculate the mean square distance. Not really looking for just an answer, I really also need an explanation so that I may be able to learn and recreate, I think I just need another while loop but I'm not sure where to put it.
import javax.swing.JOptionPane;
String a = JOptionPane.showInputDialog("Enter # of footsteps.");
int z = Integer.valueOf(a);
int x= 0; // starting x position
int y= 0; // starting y position
double r;
int counterZ = 0;
if (z < counterZ ){
System.out.println("Error");
}
while ( z > counterZ){
r=Math.random();
if (r<0.25){
x=x+1;
}
else if(r > .25 && r<0.50){
x=x-1;
}
else if(r > .5 && r<0.75){
y=y+1;
}
else{
y=y-1;
}
counterZ = counterZ + 1;
System.out.println("(" + x + "," + y + ")");
}
System.out.println("distance = " + round(sqrt((x*x)+(y*y))));
Correct me if i am wrong, My understanding is that you want to run the walk cycle a certain number of times and calculate the average distance walked on the sum of the distance of the cycles. If that is the case, then all you have to do is this,
int noc = Integer.valueOf(JOptionPane.showInputDialog("Enter # of cycles: "));
String a = JOptionPane.showInputDialog("Enter # of footsteps.");
int z = Integer.valueOf(a);
int sum = 0;
double avg = 0.0;
for(int i=0;i<noc;i++) {
sum+= randomWalk(z);
}
avg=(double)sum/noc;
System.out.println("the average distance walked in "+ noc + "cycles is "+avg);
the randomWalk() method should be like the following if you are calling it from the main method without creating an object for the class randomWalk() is residing in.
public static int randomWalk(int z) {
//place your code here, starting from the `int x=0;`
//at last instead of printing the distance walked use the following code
return (int) Math.round(Math.sqrt((x*x)+(y*y)));
}
you have also missed to call the methods round() and sqrt() using there class Math. I have correct them for you as Math.round() and Math.sqrt(). without the class name you will get a compiler error like Symbol not found. i also assume you have imported the java.lang.Math class into your program.
I'd suggest starting by indenting the code tidily so that it is more understandable.
To address your question directly, I'd suggest modifying the program so that the substance of the progam is embedded in a method (you might call it randomWalk(), perhaps) and the main() method just calls randomWalk() and does the I/O. Having done that, it would be very easy to modify the main() method to call randomWalk() many times from within a while loop.

Generate random numbers in increments

I need to generate n random numbers between a and b, but any two numbers cannot have a difference of less than c. All variables except n are floats (n is an int).
Solutions are preferred in java, but C/C++ is okay too.
Here is what code I have so far.:
static float getRandomNumberInRange(float min, float max) {
return (float) (min + (Math.random() * (max - min)));
}
static float[] randomNums(float a, float b, float c, int n) {
float minDistance = c;
float maxDistance = (b - a) - (n - 1) * c;
float[] randomNumArray = new float[n];
float random = getRandomNumberInRange(minDistance, maxDistance);
randomNumArray[0] = a + random;
for (int x = 1; x < n; x++) {
maxDistance = (b - a) - (randomNumArray[x - 1]) - (n - x - 1) * c;
random = getRandomNumberInRange(minDistance, maxDistance);
randomNumArray[x] = randomNumArray[x - 1] + random;
}
return randomNumArray;
}
If I run the function as such (10 times), I get the following output:
Input: randomNums(-1f, 1f, 0.1f, 10)
[-0.88, 0.85, 1.23, 1.3784, 1.49, 1.59, 1.69, 1.79, 1.89, 1.99]
[-0.73, -0.40, 0.17, 0.98, 1.47, 1.58, 1.69, 1.79, 1.89, 1.99]
[-0.49, 0.29, 0.54, 0.77, 1.09, 1.56, 1.69, 1.79, 1.89, 1.99]
I think a reasonable approach can be the following:
Total "space" is (b - a)
Remove the minimum required space (n-1)*c to obtain the remaining space
Shot (n-1) random numbers between 0 and 1 and scale them so that the sum is this just computed "optional space". Each of them will be a "slice" of space to be used.
First number is a
For each other number add c and the next "slice" to the previous number. Last number will be b.
If you don't want first and last to match a and b exactly then just create n+1 slices instead of n-1 and start with a+slice[0] instead of a.
The main idea is that once you remove the required spacing between the points (totalling (n-1)*c) the problem is just to find n-1 values so that the sum is the prescribed "optional space". To do this with a uniform distribution just shoot n-1 numbers, compute the sum and uniformly scale those numbers so that the sum is instead what you want by multiplying each of them by the constant factor k = wanted_sum / current_sum.
To obtain the final result you just use as spacing between a value and the previous one the sum of the mandatory part c and one of the randomly sampled variable parts.
An example in Python of the code needed for the computation is the following
space = b - a
slack = space - (n - 1)*c
slice = [random.random() for i in xrange(n-1)] # Pick (n-1) random numbers 0..1
k = slack / sum(slice) # Compute needed scaling
slice = [x*k for x in slice] # Scale to get slice sizes
result = [a]
for i in xrange(n-1):
result.append(result[-1] + slice[i] + c)
If you have random number X and you want another random number Y which is a minimum of A from X and a maximum of B from X, why not write that in your code?
float nextRandom(float base, float minDist, float maxDist) {
return base + minDist + (((float)Math.random()) * (maxDist - minDist));
}
by trying to keep the base out of the next number routine, you add a lot of complexity to your algorithm.
Though this does not exactly do what you need and does not incorporate the techinque being described in this thread, I believe that this code will prove to be useful as it will do what it seems like you want.
static float getRandomNumberInRange(float min, float max)
{
return (float) (min + (Math.random() * ((max - min))));
}
static float[] randomNums(float a, float b, float c, int n)
{
float averageDifference=(b-a)/n;
float[] randomNumArray = new float[n];
int random;
randomNumArray[0]=a+averageDifference/2;
for (int x = 1; x < n; x++)
randomNumArray[x]=randomNumArray[x-1]+averageDifference;
for (int x = 0; x < n; x++)
{
random = getRandomNumberInRange(-averageDifference/2, averageDifference/2);
randomNumArray[x]+=random;
}
return randomNumArray;
}
I need to generate n random numbers between a and b, but any two numbers cannot have a difference of less than c. All variables except n are floats (n is an int).
Solutions are preferred in java, but C/C++ is okay too.
First, what distribution? I'm going to assume a uniform distribution, but with that caveat that "any two numbers cannot have a difference of less than c". What you want is called "rejection sampling". There's a wikipedia article on the subject, plus a whole lot of other references on the 'net and in books (e.g. http://www.columbia.edu/~ks20/4703-Sigman/4703-07-Notes-ARM.pdf). Pseudocode, using some function random_uniform() that returns a random number drawn from U[0,1], and assuming a 1-based array (many languages use a 0-based array):
function generate_numbers (a, b, c, n, result)
result[1] = a + (b-a)*random_uniform()
for index from 2 to n
rejected = true
while (rejected)
result[index] = a + (b-a)*random_uniform()
rejected = abs (result[index] < result[index-1]) < c
end
end
Your solution was almost correct, here is the fix:
maxDistance = b - (randomNumArray[x - 1]) - (n - x - 1) * c;
I would do this by just generating n random numbers between a and b. Then I would sort them and get the first order differences, kicking out any numbers that generate a difference less than c, leaving me with m numbers. If m < n, I would just do it again, this time for n - m numbers, add those numbers to my original results, sort again, generate differences...and so on until I have n numbers.
Note, first order differences means x[1] - x[0], x[2] - x[1] and so on.
I don't have time to write this out in C but in R, it's pretty easy:
getRands<-function(n,a,b,c){
r<-c()
while(length(r) < n){
r<-sort(c(r,runif(n,a,b)))
r<-r[-(which(diff(r) <= c) + 1 )]
}
r
}
Note that if you are too aggresive with c relative to a and b, this kind of solution might take a long time to converge, or not converge at all if n * C > b -a
Also note, I don't mean for this R code to be a fully formed, production ready piece of code, just an illustration of the algorithm (for those who can follow R).
How about using a shifting range as you generate numbers to ensure that they don't appear too close?
static float[] randomNums(float min, float max, float separation, int n) {
float rangePerNumber = (max - min) / n;
// Check separation and range are consistent.
assert (rangePerNumber >= separation) : "You have a problem.";
float[] randomNumArray = new float[n];
// Set range for first random number
float lo = min;
float hi = lo + rangePerNumber;
for (int i = 0; i < n; ++i) {
float random = getRandomNumberInRange(lo, hi);
// Shift range for next random number.
lo = random + separation;
hi = lo + rangePerNumber;
randomNumArray[i] = random;
}
return randomNumArray;
}
I know you already accepted an answer, but I like this problem. I hope it's unique, I haven't gone through everyone's answers in detail just yet, and I need to run, so I'll just post this and hope it helps.
Think of it this way: Once you pick your first number, you have a chunk +/- c that you can no longer pick in.
So your first number is
range1=b-a
x=Random()*range1+a
At this point, x is somewhere between a and b (assuming Random() returns in 0 to 1). Now, we mark out the space we can no longer pick in
excludedMin=x-c
excludedMax=x+c
If x is close to either end, then it's easy, we just pick in the remaining space
if (excludedMin<=a)
{
range2=b-excludedMax
y=Random()*range2+excludedMax
}
Here, x is so close to a, that you won't get y between a and x, so you just pick between x+c and b. Likewise:
else if (excludedMax>=b)
{
range2=excludedMin-a
y=Random()*range2+a
}
Now if x is somewhere in the middle, we have to do a little magic
else
{
range2=b-a-2*c
y=Random()*range2+a
if (y>excludedMin) y+=2*c
}
What's going on here? Well, we know that the range y can lie in, is 2*c smaller than the whole space, so we pick a number somewhere in that smaller space. Now, if y is less than excludedMin, we know y "is to the left" of x-c, and we're all ok. However, if y>excluded min, we add 2*c (the total excluded space) to it, to ensure that it's greater than x+c, but it'll still be less than b because our range was reduced.
Now, it's easy to expand so n numbers, each time you just reduce the range by the excluded space among any of the other points. You continue until the excluded space equals the original range (b-a).
I know it's bad form to do a second answer, but I just thought of one...use a recursive search of the space:
Assume a global list of points: points
FillRandom(a,b,c)
{
range=b-a;
if (range>0)
{
x=Random()*range+a
points.Append(x)
FillRandom(a,x-c,c)
FillRandom(x+c,b,c)
}
}
I'll let you follow the recursion, but at the end, you'll have a list in points that fills the space with density 1/c

Can I calculate an element without looping through all preceding elements in my case (see the question body)?

I have 2 arrays of Doubles of the same length. Array a is filled with some data, array b is to be calculated.
Each element of the array b equals a corresponding value from array a plus a weighted sum of all preceding elements in the array b.
A weighted sum is calculated by adding all those elements each multiplied by a coefficient which equals its distance from the current element we calculate divided by number of elements in the preceding subset.
To implement this I loop through the whole preceding subset for each element I calculate.
Can this be optimized? I have not enough maths skills, but I suspect that I could only use the first preceding element to calculate every next as every element is already derived from the preceding set and contains all the information of it already weighted. Maybe I can just adjust the weight formula and get the same result without a second level looping?
This seems to be an example in Scala (I am not sure if it is correct :-]). As the real project uses negative indices, treat a(1) and a(2) as preceding a(0) in terms of the task written above.
import scala.Double.NaN
val a = Array[Double] (8.5, 3.4, 7.1, 5.12, 0.14, 5)
val b = Array[Double] (NaN, NaN, NaN, NaN, NaN, 5)
var i = b.length - 2
while (i >= 0) {
b(i) = a(i) + {
var succession = 0.0
var j = 1
while (i + j < b.length) {
succession += b (i+j) * (1.0-j.toDouble/(b.length - i))
j += 1
}
succession
}
i -= 1
}
b.foreach((n : Double) => println(n))
I assume the distance is the absolute difference of two elements.
If I understood it correctly each element of b has to be:
b(i) = a(i) + sum(j = 1 to i-1) (a(j) * (abs(a(i) - a(j)) / i )
b(i) = a(i) + sum(j = 1 to i-1) ( abs(a(j)*a(j) - a(j)*a(i)) / i )
Now, if we could write b(i+1) in terms of b(i) we would have done it.
The problem is that each weight depends on both, a(i) and a(j) (and even worse, it is the absolute difference).
That's why we can't simplify the above anymore and can't "extract" knowledge from each sum to use it in the next one.
That's what you're trying to do?
f(x_n) := g(x_0,..,x_(n-1)) + h(x_n)
The nested loop can only be optimized if we can find a equivalent function to replace g. Actually, I don't know the exact meaning of weighted sum. I guess, it's
g(x_0,..,x_(n-1)) = (x_0 + ... + x_(n-1)) / (n-1)
(adding all values and dividing by the number of values)
In that case, you could store the sum and reuse it:
a := (x_0 + ... + x_(n-2))
g(x_0,..,x_(n-1)) = (a + x_(n-1)) / (n-1)
This would eliminate the nested loop.
In terms of Java (implements my idea of a weighted sum):
double[] x = initX();
double[] y = new double[x.length];
double sum = 0;
y[0] = h(x[0]);
for (int i = 1; i < x.length; i++) {
sum = sum + x[i-1];
y[i] = sum / (i-1) + h(x[i]);
}
Is this the equation for b?
(from http://texify.com/?$b[k]%20=%20a[k]%20+%20\frac{\sum_{i%20=%200}^{k%20-%201}{a[i]%20/%20(k-i)}}{k%20-%201}$)
You said:
by adding all those elements each multiplied by a coefficient which equals its distance from the current element we calculate
Most likely you can't predict the current element from the previous elements so you will at least have to compute those distances for each element: distance(i,j) where i < n and j < i. This means looping twice.
I think this could be optimized if distance was a linear function but conventionally a distance is non linear (so that it is positive). So my guess is that you'll have to loop twice.
There are three separate cases to consider.
(1) The weights don't change.
Example/solution:
val xs = List(1,2,3,4,5)
val ws = List(3,2,5,1,4)
// Desired:
// 1
// 1*3 + 2
// 1*3 + 2*2 + 3
// 1*3 + 2*2 + 3*5 + 4
// 1*3 + 2*2 + 3*5 + 4*1 + 5
val mul = (xs,ws).zipped.map(_ * _) // 1*3, 2*2, 3*5, etc.
val cuml = mul.scanLeft(0)(_ + _) // Cumulative sums of the above
val ans = (xs,cuml).zipped.map(_ + _) // Put it all together
(2) The weights do change, but by a linear scaling factor as if they represent signed distances along a line. Then we let (d1-a)*x1 + (d2-a)*x2 + ... + (dn-a)*xn = y be our previous answer, assuming that we are at a; then if we move to b we can modify this as (d1-b)*x1... = (d1-a+a-b)*x1+... = (d1-a)*x1+(a-b)*x1+... which shows that we just need the sums of the x values and a single distance to get the new answer from our old ones. So:
val xs = List(1,2,3,4,5)
val ds = List(3,2,5,1,4) // Treat these as distances along a line
// Desired:
// 1
// (3-2)*1 + 2
// (3-5)*1 + (2-5)*2 + 3
// (3-1)*1 + (2-1)*2 + (5-1)*3 + 4
// (3-4)*1 + (2-4)*2 + (5-4)*3 + (1-4)*4 + 5
val ws = ds.map(_ - ds.head) // Distances from the first element
val mul = (xs,ws).zipped.map(_ * _)
val cuml = mul.scanLeft(0)(_ + _)
// If we used this alone we would get:
// 1
// (3-3)*1 + 2 <-- should be subtracting 2, not 3!
// (3-3)*1 + (2-3)*2 + 3 <-- should be subtracting 5, not 3!
// etc.
val cumlx = xs.scanLeft(0)(_ + _) // Need this to fix up our sums
val fix = (cumlx,ws).zipped.map(-1 * _ * _) // This will actually do it
val ans = (xs,cuml,fix).zipped.map(_ + _ + _)
The best way to understand how this works is to take it apart statement by statement and write things out by hand to verify that it is actually computing what we want it to compute.
(3) The weights change in no consistent manner as you advance. Distances to points in a plane tend to have that property, since the nonlinearity of the square root basically means that you have to calculate each one over again. So you just have to do the whole calculation each time.

Categories