What is wrong with this source code for sine? - java

I'm quite good enough with Java syntax and just decided to put it to work by creating a code for sine based on an algorithm I created earlier. I know Math.sin helps you evaluate sine but I just for the fun, decided to go on an create my own source code.
However, angles between 60° and 120° and also between 240° and 300° give wrong answers and I have no idea why. Could someone please help me find the error? I've tried everything to detect it but failed.
import java.util.Scanner;
public class Sine {
public static void main(String[] args) {
// This code solves sine according yo the general expansion of sine
// sin x = x - x³/3! +x^5/5! - x^7/7! +...
Scanner scanner = new Scanner(System.in);
double answer = scanner.nextDouble();
scanner.close();
answer = simplify(answer);
answer = converttoradian(answer);
answer = continued(answer);
System.out.println(answer);
}
// This Makes all the angles that are more than 360
// To become less than 360 and Generates the simplified
// Angles for obtuse and reflex angles
static double simplify(double x) {
if (x >= 360) {
x = x - 360;
return simplify(x);
}
else if (x <= -360) {
x = x + 360;
return simplify(x);
}
else if (x > 90 && x <= 270) {
x = 180 - x;
return x;
}
else if (x >= 270) {
x = x - 360;
return x;
}
else if (x <= -90 && x > -270) {
x = -x - 180;
return x;
}
else if (x <= -270) {
x = x + 360;
return x;
}
else {
return x;
}
}
// Simple enough and explains itself
// Converts the angles to radian
static double converttoradian(double d) {
d *= Math.PI;
d /= 180.0;
return d;
}
// This Method about to open generates each term and adds them together
// The number of terms solved in this case is 33
static double continued(double d) {
double answer = 0.0;
int index = 1;
double one = d;
for (int i = 0; i < 33; i++) {
double result = 0.0;
for (int x = 1; x < index; x++) {
d = d * one;
}
long here = factorial(index);
result = d / here;
if ((index - 1) % 4 == 0) {
answer = answer + result;
index = index + 2;
}
else {
answer = answer - result;
index = index + 2;
}
}
return answer;
}
// Evaluates factorials
static long factorial(int n) {
long one = 1;
long m = (long) n;
if (m == 0 || m == 1) {
one = 1;
return one;
}
else {
while (m > 1) {
one *= m;
m--;
}
return one;
}
}
}

There was a lot going on in your program and some unnecessary code. You were on the right track, though. I made some changes to simplify the calculations. You should be able to follow them.
Specifically.
Alternate the sign. Start out with sign = 1, then set sign = -sign for subsequent terms.
For the denominator and factorial, I just used the for loop, starting at 1 and incrementing by 2 to get 1,3,5,7
For powers of the same value, I just multiplied d by a dSquared constant to achieve the same.
I rewrote the factorial to make it simpler.
To reduce large values of d I just used the remainder operator to get them less than 360.
I added some print statements to show calculation progress and to ensure things were working correctly.
And finally, the maximum factorial that will fit in a long is 20!. After that they turn negative due to overflow. So the number of terms needed to be reduced.
public class Sine {
public static void main(String[] args) {
// This code solves sine according yo the general expansion of sine
// sin x = x - x³/3! +x^5/5! - x^7/7! +...
for (double degrees = 0; degrees < 700; degrees += 17) {
double simplified_degrees = simplify(degrees);
System.out.println("simplified_degrees = " + simplified_degrees);
double radians = converttoradian(simplified_degrees);
System.out.println("radians = " + radians);
double sin = continued(radians);
System.out.println(sin);
System.out.println(Math.sin(radians));
System.out.println("------------------------------------------");
}
}
// This Makes all the angles that are more than 360
// To become less than 360 and Generates the simplified
// Angles for obtuse and reflex angles
static double simplify(double x) {
x = x % 360;
return x;
}
// Simple enough and explains itself
// Converts the angles to radian
static double converttoradian(double d) {
return Math.PI / 180. * d;
}
// This Method about to open generates each term and adds them together
// The number of terms solved in this case is 33
static double continued(double d) {
double result = 0;
double sign = 1;
double dSquared = d * d;
int pow = 1;
for (int pow = 1; pow < 21; pow += 2) {
long fact = factorial(pow);
System.out.println("d = " + d + ", fact = " + fact + ", pow = " + pow
+ ", sign = " + sign);
result = result + (d / fact) * sign;
d *= dSquared; // effective powers 3, 5, 7,9
sign = -sign; // alternate sign for every other term
}
return result;
}
// Evaluates factorials
static long factorial(int n) {
if (n == 0 || n == 1) {
return 1;
}
long fact = 1;
for (long i = 2; i <= n; i++) {
fact *= i;
}
return fact;
}
}

Related

Issue finding euler's number in java

i have to find e, which is 1/0! + 1/1! + 1/2! + 1/3!... + 1/n! given n as a parameter and i'm having trouble getting the correct answer.
public double Factorial(int n) {
long fact = 1;
for (int i = 1; i <= n; ++i) {
fact *= i;
}
return fact;
}
public double euler(int n) {
double y = 0;
for (int x = 0; x <= n; x++) {
double e = 1 / Factorial(n);
y = y + e;
}
return y;
when i input 10, this outputs 2.7557319223985893E-6 when i should be getting 2.7182818011463845. i ran through the code a few times but i can't figure out the issue. any help is appreciated.
The answer given in the comments addresses the problem. And since you have the algorithm down you may be interested in the following:
A factorial method is not necessary. Since each subsequent value of n! is n! * (n+1) you can work it into your main loop as follows.
// initialize fact to 0!
double fact = 1;
// first Euler term 1/0!
double y = fact;
for (int x = 1; x <= n; x++) {
// next factorial
fact *= x;
// subsequent terms
y += (1 / fact);
}
System.out.println(y);
Prints
2.7182818011463845
And Euler's number is also the limit of (1 + r)(1/r) as r approaches 0.
double r = .000000001;
System.out.println(Math.pow(1 + r, 1/r));
2.71828205201156

What causes Java version Random walk doesn't converge to expected value?

Basically, I implemented a Random walk program in Java. And I know the distance should converge to l * (n ^ 0.5)(l is the step length, n is the total steps). If let l equals to 1, then d = n ^ 0.5 or in other words: d = sqrt(n).
But, strangly, although I cannot find any error in my code, it just converges to unexpected value. For example, given l = 1, n = 100, d should converge to 10, but actually it converges to 8.86 after 1000000 times experiments.
Here is my code:
public class RandomWalk {
private int x = 0;
private int y = 0;
private final Random random = new Random();
private void move(int dx, int dy) {
x += dx;
y += dy;
}
private void randomWalk(int m) {
for (int i = 0; i < m; i++)
randomMove();
}
private void randomMove() {
boolean xOry = random.nextBoolean();
boolean plusOrminus = random.nextBoolean();
int delta = plusOrminus ? 1 : -1;
int dx = xOry ? delta : 0, dy = xOry ? 0 : delta;
move(dx, dy);
}
public double distance() {
return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
}
public static double randomWalkMulti(int m, int n) {
double totalDistance = 0;
for (int i = 0; i < n; i++){
RandomWalk walk = new RandomWalk();
walk.randomWalk(m);
totalDistance += walk.distance();
}
return totalDistance/n ;
}
}
I've thought some possiblities. First I think it may be caused by that the generated boolean by random has bias. Second I think it may be caused by float precision lost. But as this is just a very simple use case, I don't think these two situations are possible.
Could any one tell me why it doesn't work as expected?
I don't think it's true that the distance should average out to √n. According to https://math.stackexchange.com/questions/103142/expected-value-of-random-walk, the square of the distance should average out to n, but that's not the same thing (since the average of the square roots of a set of numbers is not the same as the square root of their average).

Java won't print output

I'm using binary search to write a simple square root calculator that takes in doubles in Java. When I tried to test my code by printing out the answer in the main function, however, nothing got printed out in the terminal. I also got errors Possible lossy conversion from double to float......
Here is my code:
public class MyMath{
public static double sqrt(double n){
double u = 1;
double l = 0;
float m = (u + l) / 2;
double norm_input = 1;
float acc = 0.00000000001;
double answer = 0;
if ((n > 0) && (n < 1)){
if ((m * m) < n){
l = m;
}else{
u = m;
}
answer = (u + l) / 2;
return answer;
}else{
int count = 0;
while (n > 1){
n = n / 4;
norm_input = norm_input * 2;
count++;
}
while ((u - l) > acc){
if ((m * m) < n){
l = m;
}else{
u = m;
}
}
answer = (u + l) / 2 * norm_input;
return answer;
}
}
public static void main(String[] args){
double a = new MyMath().sqrt(4);
System.out.println(a);
}
}
It is stuck in infinite loop in second while condition, that's the reason it is not printing values to console.
float m = (u + l) / 2;
Here you have to type cast into float because when two datatype variable participated in division the result would be in higher data type.
float acc = 0.00000000001;
Here also you have type cast because by default java treats a decimal point value as Double.
while ((u - l) > acc){
if ((m * m) < n){
l = m;
}
}
and your code here is going to infinite loop .

Divide and Conquer Closest Pair Algorithm

I'm trying to create an algorithm that returns the closest pair from randomly generated points. I have finished the algorithm, however the divide and conquer method of the algorithm is not much faster than the brute-force method. What can I do to optimize the code so that it returns at (n log n) time?
import java.util.*;
import java.lang.*;
import static java.lang.Math.min;
import static java.lang.StrictMath.abs;
public class closestPair {
private static Random randomGenerator; // for random numbers
public static class Point implements Comparable<Point> {
public long x, y;
// Constructor
public Point(long x, long y) {
this.x = x;
this.y = y;
}
public int compareTo(Point p) {
// compare this and p and there are three results: >0, ==0, or <0
if (this.x == p.x) {
if (this.y == p.y)
return 0;
else
return (this.y > p.y)? 1 : -1;
}
else
return (this.x > p.x)? 1 : -1;
}
public String toString() {
return " ("+Long.toString(this.x)+","+Long.toString(this.y)+")";
}
public double distance(Point p) {
long dx = (this.x - p.x);
long dy = (this.y - p.y);
return Math.sqrt(dx*dx + dy*dy);
}
}
public static Point[] plane;
public static Point[] T;
public static Point[] Y;
public static int N; // number of points in the plane
public static void main(String[] args) {
// Read in the Size of a maze
Scanner scan = new Scanner(System.in);
try {
System.out.println("How many points in your plane? ");
N = scan.nextInt();
}
catch(Exception ex){
ex.printStackTrace();
}
scan.close();
// Create plane of N points.
plane = new Point[N];
Y = new Point[N];
T = new Point[N];
randomGenerator = new Random();
for (int i = 0; i < N; ++i) {
long x = randomGenerator.nextInt(N<<6);
long y = randomGenerator.nextInt(N<<6);
plane[i] = new Point(x, y);
}
Arrays.sort(plane); // sort points according to compareTo.
for (int i = 1; i < N; ++i) // make all x's distinct.
if (plane[i-1].x >= plane[i].x) plane[i].x = plane[i-1].x + 1;
//for (int i = 1; i < N; i++)
// if (plane[i-1].y >= plane[i].y) plane[i].y = plane[i-1].y + 1;
//
//
System.out.println(N + " points are randomly created.");
System.out.println("The first two points are"+plane[0]+" and"+plane[1]);
System.out.println("The distance of the first two points is "+plane[0].distance(plane[1]));
long start = System.currentTimeMillis();
// Compute the minimal distance of any pair of points by exhaustive search.
double min1 = minDisSimple();
long end = System.currentTimeMillis();
System.out.println("The distance of the two closest points by minDisSimple is "+min1);
System.out.println("The running time for minDisSimple is "+(end-start)+" mms");
// Compute the minimal distance of any pair of points by divide-and-conquer
long start1 = System.currentTimeMillis();
double min2 = minDisDivideConquer(0, N-1);
long end1 = System.currentTimeMillis();
System.out.println("The distance of the two closest points by misDisDivideConquer is "+min2);
System.out.println("The running time for misDisDivideConquer is "+(end1-start1)+" mms");
}
static double minDisSimple() {
// A straightforward method for computing the distance
// of the two closest points in plane[0..N-1].
// to be completed
double midDis = Double.POSITIVE_INFINITY;
for (int i = 0; i < N - 1; i++) {
for (int j = i + 1; j < N; j++) {
if (plane[i].distance(plane[j]) < midDis){
midDis = plane[i].distance(plane[j]);
}
}
}
return midDis;
}
static void exchange(int i, int j) {
Point x = plane[i];
plane[i] = plane[j];
plane[j] = x;
}
static double minDisDivideConquer(int low, int high) {
// Initialize necessary values
double minIntermediate;
double minmin;
double minDis;
if (high == low+1) { // two points
if (plane[low].y > plane[high].y) exchange(low, high);
return plane[low].distance(plane[high]);
}
else if (high == low+2) { // three points
// sort these points by y-coordinate
if (plane[low].y > plane[high].y) exchange(low, high);
if (plane[low].y > plane[low+1].y) exchange(low, low+1);
else if (plane[low+1].y > plane[high].y) exchange(low+1, high);
// compute pairwise distances
double d1 = plane[low].distance(plane[high]);
double d2 = plane[low].distance(plane[low+1]);
double d3 = plane[low+1].distance(plane[high]);
return ((d1 < d2)? ((d1 < d3)? d1 : d3) : (d2 < d3)? d2 : d3); // return min(d1, d2, d3)
} else { // 4 or more points: Divide and conquer
int mid = (high + low)/2;
double lowerPartMin = minDisDivideConquer(low,mid);
double upperPartMin = minDisDivideConquer(mid+1,high);
minIntermediate = min(lowerPartMin, upperPartMin);
int k = 0;
double x0 = plane[mid].x;
for(int i = 1; i < N; i++){
if(abs(plane[i].x-x0) <= minIntermediate){
k++;
T[k] = plane[i];
}
}
minmin = 2 * minIntermediate;
for (int i = 1; i < k-1; i++){
for(int j = i + 1; j < min(i+7,k);j++){
double distance0 = abs(T[i].distance(T[j]));
if(distance0 < minmin){
minmin = distance0;
}
}
}
minDis = min(minmin, minIntermediate);
}
return minDis;
}
}
Use the following method with the change for minDisSimple. You can get more performance.
static double minDisSimple() {
// A straightforward method for computing the distance
// of the two closest points in plane[0..N-1].
// to be completed
double midDis = Double.POSITIVE_INFINITY;
double temp;
for (int i = 0; i < N - 1; i++) {
for (int j = i + 1; j < N; j++) {
temp = plane[i].distance(plane[j]);
if (temp < midDis) {
midDis = temp;
}
}
}
return midDis;
}
Performance wise for small amount of points simple method is good but larger amount of points Divide and Conquer is good. Try number of points with 10, 100, 1000, 10000, 100000, 1000000.
One critical aspect in the minDisDivideConquer() is that the loop that constructs the auxiliary array T iterates through all the N points. Since there are O(N) recursive calls in total, making this pass through all the N points every time leads to a complexity of O(N^2), equivalent to that of the simple algorithm.
The loop should actually only consider the points with indices between low and high. Furthermore, it could be split into two separate loops that start from mid (forward and backward), and break when the checked distance is already too large.
Another possible improvement for the minDisDivideConquer() method, in the "4 or more points" situation is to prevent looking into pairs that were already considered in the recursive calls.
If my understanding is correct, the array T contains those points that are close enough on x axis to the mid point, so that there is a chance that a pair of points in T generates a distance smaller than those from the individual half sets.
However, it is not necessary to look into points that are both before mid, or both after mid (since these pairs were already considered in the recursive calls).
Thus, a possible optimization is to construct two lists T_left and T_right (instead of T) and check distances between pairs of points such that one is on the left of mid, and the other to the right.
This way, instead of computing |T| * (|T| - 1) / 2 distances, we would only look into |T_left| * |T_right| pairs, with |T_left| + |T_right| = |T|. This value is at most (|T| / 2) * (|T| / 2) = |T| ^ 2 / 4, i.e. around 2 times fewer distances than before (this is in the worst case, but the actual number of pairs can also be much smaller, inclusively zero).

Java Nested Loops Issue

so I've been working on this code for a while now, and I've reached a standstill. It's a project for school and it came in two parts, the first part was no issue at all.
A drunkard begins walking aimlessly, starting at a lamp post. At each time step, the drunkard forgets where he or she is, and takes one step at random, either north, east, south, or west, with probability 25%. How far will the drunkard be from the lamp post after N steps?
Write a program RandomWalker.java that takes an integer command-line argument N and simulates the motion of a random walker for N steps. After each step, print the location of the random walker, treating the lamp post as the origin (0, 0). Also, print the square of the final distance from the origin.
My code for this part of the problem was:
import java.util. *;
import java.math. *;
public class RandomWalker {
public static void main(String args[]){
int N = Integer.parseInt(args[0]);
Random rand = new Random();
int x = 0;
int y = 0;
int XorY;
int dist;
int count =0;
while(count<N){
XorY = rand.nextInt(2);
dist = rand.nextInt(2);
if(XorY==0){
if(dist==0)
dist = -1;
x += dist;
System.out.println("("+x+", " +y+")");
}
else{
if(dist==0)
dist = -1;
y += dist;
System.out.println("("+x+", " +y+")");
}
count ++;
}
System.out.println("Squared Distance = " + (x*x + y*y));
}
}
For the second part of the problem-
Write a program RandomWalkers.java that takes two command-line arguments N and T. In each of T independent experiments, simulate a random walk of N steps and compute the squared distance. Output the mean squared distance (the average of the T squared distances.)
% java RandomWalkers 100 10000
squared distance = 101.446
% java RandomWalkers 100 10000
mean squared distance = 99.1674
% java RandomWalkers 200 1000
mean squared distance = 195.75
The code I came up with is-
import java.util.*;
import java.math.*;
public class RandomWalkers {
public static void main(String args[]) {
Random rand = new Random();
int N = Integer.parseInt(args[0]);
int T = Integer.parseInt(args[1]);
double avgDist =0;
int stepCount =0;
int trialCount =0;
int x = 0;
int y = 0;
int XorY;
int dist;
while(trialCount<T){
while(stepCount<N){
XorY = rand.nextInt(2);
dist = rand.nextInt(2);
if(XorY==0){
if(dist==0)
dist = -1;
x += dist;
}
else{
if(dist==0)
dist = -1;
y += dist;
}
stepCount ++;
}
avgDist += ((x*x) + (y*y));
trialCount++;
}
System.out.println("Mean Squared Distance = " + avgDist/(double)trialCount);
}
}
I have been stumped here for a really long time, the code compiles and runs but it seems that all it is giving me is a single trial value, and not the desired average. Any help is appreciated, thank you very much. (Also sorry for the improper formatting, I am new here and tried my best).
The solution with the nested while loop inside the for loop is shown below. You have to reset the x, y and distance variables after each trial. Or, even better, to define and initialize them to 0 at the beginning of the for loop, like so:
public class RandomWalkers {
public static void main(String[] args) {
int r = Integer.parseInt(args[0]);
int trials = Integer.parseInt(args[1]);
double steps = 0.0;
for (int j = 0; j < trials; j++) { // run one experiment
int x = 0;
int y = 0;
int distance = 0;
while (distance < r) { // simulate one random walking
double i = Math.random();
if (i < 0.25) {
y += 1;
distance = Math.abs(x) + Math.abs(y);
steps += 1;
}
if (i >= 0.25 && i < 0.5) {
x += 1;
distance = Math.abs(x) + Math.abs(y);
steps += 1;
}
if (i >= 0.5 && i < 0.75) {
y -= 1;
distance = Math.abs(x) + Math.abs(y);
steps += 1;
}
if (i >= 0.75 && i < 1) {
x -= 1;
distance = Math.abs(x) + Math.abs(y);
steps += 1;
}
}
}
System.out.println("average number of steps = " + steps / trials);
}
}

Categories

Resources