I am using Math.PI in my example, so it is a double. It is a simple code but there is a bit I am not sure how to do:
I want the code to calculate the fundamental period X of a sin or cos function with a multiplier value a given by the user. The n value is initialized at n=1 and is an integer value.
If the result of (2 * pi * n)/a = X is lower than pi then n should increment, and it should keep going until that number is a multiple of pi, then print the result.
Just to clarify: a is a multiplier of x which goes in the function sin or cos like this:
cos(ax)
sin(ax)
The bit I am having the trouble with is working out whether the number is a multiple of pi (provided it's already greater than pi, that is).
This is about as far as I got and it's incomplete.
public void printSinusoidalPeriod(double multiplier /* this would be `a` */){
double pi=Math.PI;
double p = (2 * pi * (double) n) / multiplier;
while(p<pi){
if(n%pi==0){
n=n+1;
System.out.println(n);
p = (2 * pi * (double) n) / multiplier;
}
}
p= (double)Math.round(p * 100) / 100;
System.out.println("period of function is = " + p + " and n = " + n);
}
It seems like it's not going into the if statement and getting caught in the while loop
If I understand your problem correctly, I had to solve a similar problem to this before using php. Not sure what the correct syntax is for javascript but maybe you should keep a counter that continues until (x/pi) is an integer which would indicate it is a multiple of pi..
I know this isn't the correct code but something like:
while (!isint(x/pi)) {
x++;
}
if (isint(x/pi)) {
//CODE TO EXECUTE
}
If I understand you correctly
while((2 * pi * n)/a)<pi)
{
if(!(n%pi==0))
{
n++;
}
}
multiple of y is the part you need to figure out yourself. but this should help you with the logic, If I have understood u correctly.
You appear to be calculating when
(2 * pi * n)/a = m * pi where m is some integer multiple.
so
2 * pi * n = m * pi * a
2 * n = m * a
n = m * a / 2
You other constraint is
(2 * pi * n)/a < pi
so
2 * pi * n < pi * a
2 * n < a
n < a / 2;
For both equations to be true, m must be an integer less than 1, but since you are starting at 1 for n it will never be true.
Ok here's how I did it in the end, with the help of the suggestions here.
public void printSinusoidalPeriod(double a){
double pi=Math.PI;
double p=m*pi;
while(n<a/2){
if((double)Math.round((n*pi)%pi)!=0.01){
n=n+1;
m = (int) Math.round(((2 * (double) n) / a));
p= (double)Math.round(m * pi * 100) / 100;
p=p*n;
}
}
System.out.println("period of function is = " + p + " and n = " + n);
System.out.println("Check: p/n = " + p/n);
}
Please let me know if you can spot any problems with the logic. I have not gone through many possibities yet, but the ones I did, looked okay to me.
Related
I wrote a program to calculate the PI number with Leibniz formula:
[
I wrote a for-loop with type of initialization is "int" , the loop works fine but when i changed the initialization type to "long" the result is changed. This only happens when the loop times over a billion. This makes the "int - loop" calculates PI more accurate than "long - loop". I don't know why this happens. Please help me to understand this issue. Thanks! and here is my code.
public static void main(String[] args) {
double result1 = 0;
double result2 = 0;
double sign = 1;
for (int i = 0; i <= 1607702095; i++) {
result1 += sign/(2 * i + 1);
sign *= -1;
}
sign = 1;
for (long j = 0; j <= 1607702095; j++) {
result2 += sign/(2 * j + 1);
sign *= -1;
}
System.out.println("result1 " + result1 * 4);
System.out.println("result2 " + result2 * 4);
System.out.println("pi " + Math.PI);
}
And the result is:
result1 3.141592653576877
result2 3.1415926529660116
pi 3.141592653589793
Actually, your first loop would have int overflow in the calculation of (2 * i + 1) when i is large enough, so I wouldn't rely on the output of it.
The second loop, on the other hand, produces a more correct output, since (2 * j + 1) doesn't overflow, since it performs long multiplication.
This makes the "int - loop" calculates PI more accurate than "long - loop"
That's probably just a coincidence, since the calculations in the int loop overflow.
Because you are getting overflow at the line
result1 += sign/(2 * i + 1);
Where the value of 2*i cross the max integer value
int range is -2,147,483,648 to 2,147,483,647 but when you do 2*i for greater value it crosses that range.
Better to be stick with long and that gives you correct output.
2 * i when i is close to the end of your loop will overflow the max value for an int which is 2147483647.
Using a long that operation doesn't overflow.
The correct procedure is using a long type. Probably because values are added and removed around the correct PI for some strange behavior the overflows momentarily compute to a value closer to the right PI.
I suppose that change the limit of the for loop of few values will change the final result to a value that is more far from the right PI.
You have integer overflow.
The max capacity of a signed int is (2^31)-1, or 2,147,483,647.
(1,607,702,095 * 2) is 3215404190, which is bigger than 2,147,483,647.
When you change i to a long you increase the capacity of i to (2^63)-1.
Noticed everyone is pointig the integer overflow, but you might want a solution. (If you already have one, please ignore the following :) )
Having the overflow in the (2 * i + 1) part of the code, you should max the i in the for loop to (Integer.MAX_VALUE / 2 - 1), which results in:
for (int i = 0; i <= (Integer.MAX_VALUE / 2 - 1); i++) {
result1 += sign/(2 * i + 1);
sign *= -1;
}
You can also do that to the long part with (Long.MAX_VALUE / 2 - 1) but it will be running for a VERY LONG time.
If you are unsure of what "Poisson Distrubtion using Normal Approximation" means, follow this link and check the texts inside the yellow box.
https://onlinecourses.science.psu.edu/stat414/node/180
Here, is the simple snapshot of the math from the link.
P(Y≥9) = P(Y>8.5) = P(Z>(8.5−6.5)/√6.5) = P(Z>0.78)= 0.218
So to get the value in .218, we use Simpson's integration rule which
integrates the function(Implemented in method named "f" from code below) from "negative
infinity" to the value that equals to this >> "((8.5−6.5)/√6.5))"
R successfully gives the correct output. But in Java when i implemented the code
below copied from "http://introcs.cs.princeton.edu/java/93integration/SimpsonsRule.java.html"
I get "0.28360853976343986" which should have been ".218" Is it any how because of the negative infinity value I am using, which is "Double.MIN_VALUE"
This is the code in Java. See at the very end for my INPUTS in the main method.
* Standard normal distribution density function.
* Replace with any sufficiently smooth function.
**********************************************************************/
public static double f(double x) {
return Math.exp(- x * x / 2) / Math.sqrt(2 * Math.PI);
}
/**********************************************************************
* Integrate f from a to b using Simpson's rule.
* Increase N for more precision.
**********************************************************************/
public static double integrate(double a, double b) {
int N = 10000; // precision parameter
double h = (b - a) / (N - 1); // step size
// 1/3 terms
double sum = 1.0 / 3.0 * (f(a) + f(b));
// 4/3 terms
for (int i = 1; i < N - 1; i += 2) {
double x = a + h * i;
sum += 4.0 / 3.0 * f(x);
}
// 2/3 terms
for (int i = 2; i < N - 1; i += 2) {
double x = a + h * i;
sum += 2.0 / 3.0 * f(x);
}
return sum * h;
}
// sample client program
public static void main(String[] args) {
double z = (8.5-6.5)/Math.sqrt(6.5);
double a = Double.MIN_VALUE;
double b = z;
System.out.println(integrate(a, b));
}
Anybody has any ideas? I tried using Apache math's "PoissonDistribution" class's method "normalApproximateProbability(int x)". But the problem is this method takes an "int".
Anyone has any better ideas on how do I get the correct output or any other code. I have used another library for simpson too but I get the same output.
I need this to be done in Java.
I tried to test the code by writing another method that implements Simpson's 3/8 rule instead of your integrate function. It gave the same result as the one you obtained at first time. So i think the difference arises most probably from rounding errors.
I'm working on a Java program that prints a sine wave to the console. This is what I've written so far:
int num = 7;
for (double y = 2; y >= 0; y-=0.2) {
for (double x = 0; x <= num; x+=0.2) {
if ( ((0.1+x) >= Math.asin((double)y-1)) && (((double)x-0.1) <= Math.asin((double)y-1)) )
System.out.print('*');
else
System.out.print(' ');
}
System.out.println();
}
Essentially, this program treats each character on each line as a 0.2 x 0.2 area on a coordinate plane. If the sine function crosses this area, an asterisk is printed to the screen. Otherwise, a space is printed.
When run, this is printed to the console:
*
*
*
*
*
*
Can anybody tell me why my program stops after printing the first quarter of the wave?
The reason it only prints the first quarter of the sine wave is because of the indicated range of Math.asin:
Returns the arc sine of a value; the returned angle is in the range -pi/2 through pi/2.
Once you advance x past Math.PI / 2, then the if statement's condition will always be false.
You can take advantage of the fact that
sin(π - x) = sin(x)
and
sin(2π - x) = -sin(x)
by including more conditions. (I've also removed the unnecessary casts to double for clarity.)
if ( (0.1+x >= Math.asin(y-1)) && (x-0.1 <= Math.asin(y-1)) ||
(0.1+x >= Math.PI - Math.asin(y-1)) && (x-0.1 <= Math.PI - Math.asin(y-1))
(2*Math.PI -(0.1 + x) <= -Math.asin(y-1)) && (2*Math.PI -(x-0.1) >= -Math.asin(y-1)) )
Output:
*
* *
* *
* * *
* * *
* * *
* *
* *
* *
* *
*
The problem seems to arise from the condition of your if-statement, which almost always evaluates to false. You should check the calculus behind your conditional expression. I find increasing num does not really help here.
Maybe you should print another character instead of a whitespace by replacing System.out.print(' '); with System.out.print('_'); for instance. This way you may be able to figure out why your program behaves that way. Reworking that algorithm of yours may also be helpful.
Edit: Whoops, skimmed the code a little too fast. This is wrong.
Well, you set num to 7, then in your loop you take x from 0 to num-1, so you're only looping over 7 columns. Increase num and your graph should add additional columns. You'll have to increase the range of y values you loop over too, if you want the graph to extend to negative numbers.
However, your algorithm is extremely inefficient. You're calculating asin(y-1) twice for every square on your graph, when all you really need to do is calculate sin(x) once for every column. Why not just fill an array with precalculated sine values and then consult the array while drawing the graph? (I realize, of course, that on a modern computer it's fast enough to be practically irrelevant either way.)
Thank you all for the help! Based on #dasblinkenlight's suggestion to use sin instead of asin, I found a very simple solution:
int num = 7;
for (double y = 1; y >= -1; y-=0.2) {
for (double x = 0; x <= num; x+=0.2) {
double sin = Math.sin(x);
if ( (0.1+y) >= sin && (y-0.1) <= sin )
System.out.print('*');
else
System.out.print(' ');
}
System.out.println();
}
This prints this to the console:
*****
** *
* **
* * **
* * *
* * *
* *
* *
* *
** **
****
In VBA code, here is the loop:
For i = 0 To 50
sum = sum + Exp(-lambda * T) * (lambda * T) ^ i / Application.Fact(i) * X
Next
In Java I converted to code like this:
for (int i = 0; i < 50; i++)
{
sum = sum + Math.exp(-lambda * T) * Math.pow(lambda * T , i) / (i*=1) * X;
}
But It didnt work. Any idea how to write Application.Fact(i) function in Java?
You need to implement factorial(i) yourself in Java.
Just a hint: make sure it does not overflow.
If needed use the BigInteger class (from the Java libraries).
I'm trying to make a program that calculates the required score to level in a game and the equation works fine on my calculator but not when i try changing it to work with java.
the equation is 5,000 / 3 * (4n^3 - 3n^2 - n) + 1.25 * 1.8^(n - 60) for example level 49 you should need to have a total score of 772240000 points and the calculator gives this answer but my java program doesn't. here is the code i tried.
for (int i = 0; i <= 100; i++) {
double score = (double) ((5000 / 3) * (Math.pow(4 * i, 3) - Math.pow(3 * i, 2) - i) + (1.25 * Math.pow(1.8, i - 60)));
System.out.println("Level " + i + " requires " + (long) score);
}
This doesnt seem to work right and gives 12513130000 as the required points for lvl 49. If anyone can get it to work would you miind explaining what i did wrong.
You're messing up your Math.pow calls, but you can avoid some of them entirely:
double score = (double) ((5000 / 3) * (4 * i * i * i - 3 * i * i - i) + (1.25 * Math.pow(1.8, i - 60)));
Here's what's wrong: Math.pow(4 * i, 3) is actually (4i)^3 and not 4(i^3). To do the latter, you would need the following:
4 * Math.pow(i, 3)
I'm not entirely sure about the integer division part (you are casting it to double), but you may have to change 5000 / 3 to 5000.0 / 3.
Your problem is inside Math.pow - you're multiplying your index value by a scalar each time.
4 * Math.pow(i, 3)
And
3 * Math.pow(i, 2)
Should fix it.
Edit: And the integer division mentioned in other answers.