Simpson's double integral won't work in java - java

So I had to write an algorithm for the Simpson's double integral so I can find the answer in a much faster manner. I had a guide that showed the steps to follow to write this program. After following this guide and running it in netbeans, I found out that the values coming out of the program where not really close to the real answer. This is the code that I written in java:
//INPUT
double a = 0,b = 1; // Endpoints
int m = 8,n = 4;
double K1 = 0, K2 = 0, K3 = 0;
//OUPUT
//Step 1
double h = (b - a) / n;
double j1 = 0; //End terms
double j2 = 0; //Even terms
double j3 = 0; //Odd terms
//Step 2
for(int i = 0; i <= n; i++){
//Step 3
double x = a + (i * h);
double hX = (d(x) - c(x)) / m;
K1 = f(x, c(x)) + f(x, d(x)); // End terms
//Step 4
for (int j = 1; j < (m-1); j++){
//Step 5
double y = c(x) + (j * hX);
double q = f(x,y);
//Step 6
if (j % 2 == 0){
K2 = K2 + q;
}
else
K3 = K3 + q;
}
//Step 7
double l = (K1 + (2*K2) + (4*K3)) * (hX / 3);
//Step 8
if (i == 0 || i == n)
j1 = j1 + l;
else if (i % 2 == 0)
j2 = j2 + l;
else
j3 = j3 + l;
}
double j = h * (j1 + (2 * j2) + (4 * j3)) / 3;
System.out.println("j = " + j);
}
public static double c(double x){
return x;
}
public static double d(double x){
return 2 * x;
}
public static double f(double x, double y){
return (Math.pow(y, 2) + Math.pow(x, 3));
}
I tried debugging the program several times but I haven't yet found why I am encountering this mistake. If there's any mistake that you find in my code please let me know to see if it fixes it. For the given example, I am getting the value of 0.9069281684027777 instead of having the correct value which is 0.7838542. Thank you for your help. You can also see the guide that I followed to be able to create this program.

I did not check the math, the large error seems to indicate an error in the algorithm implemented. The for-bounds are dubious. And floating point errors exist.
Instead of multiplying a fraction by a running index (which would multiply the floating point approximation error in the fraction), better do:
Instead:
double h = (b - a) / n;
for (int i = 0; i <= n; i++) {
double x = a + (i * h);
do
for (int i = 0; i < n; i++) {
double x = a + i * (b - a) / n;
or
for (int i = 0; i <= n; i++) {
double x = a + i * (b - a) / (n + 1);
The boundary n being a bit unclear to me.

Related

Loss of accuracy with floats

I am trying to compute a summation of float numbers. All small numbers output properly, when I use very large numbers as inputs, the output is always off by a few integers. For example, H = 5764801 W = 1679616, on paper, works out as 335923 30275911. In my program though, 335923 30275908 is printed instead. Here is the code:
public void printOutput(int H, int W) // The inputs
{
if(H == 1 && W == 1)
{
System.out.println(0 + " " + 1);
return;
}
List<Integer> pfw = primeFactors(W);
int y = 1;
while(H != (int) (Math.pow(Math.pow(W, 1f/y) + 1f, y))) y++;
final float N = findWholeNumber(pfw);
float height = 0;
for(int x = 1; x <= y + 1; x++)
{
height += (float) (W * Math.pow((N + 1f) / N, x-1f) + 1e-8); //Here is the summation
}
float cats = 1;
for(int x = 2; x <= y + 1; x++)
cats += (float) (Math.pow(N, x-1));
int notWorking = (int) (cats - W);
System.out.println(notWorking + " " + (int)height); //Outputs printing
}
private int findWholeNumber(List<Integer> factors)
{
List<Integer> common = new ArrayList<Integer>();
for(int i = 0; i < factors.size(); i++)
{
if(common.contains(factors.get(i))) continue;
common.add(factors.get(i));
}
int num = common.get(0);
for(int i = 1; i < common.size(); i++)
num *= common.get(i);
return num;
}
private List<Integer> primeFactors(int num)
{
List<Integer> pf = new ArrayList<Integer>();
if(num == 1)
{
pf.add(1);
return pf;
}
for(int j = 2; j <= num; j++)
while(num % j == 0) // is prime
{
pf.add(j);
num /= j;
}
return pf;
}
}
Floating point numbers have a limited precision as mantissa has a limited width.
You could try double for your case which precision is more (as its mantissa is wider), but it is also limited.
More information: https://en.wikipedia.org/wiki/IEEE_floating_point#IEEE_754-2008 and What is the maximum number in the mantissa part of a Java float?
If you need to have an unlimited precision, try BigDecimal. The count of significant digits there is only limited by the amount of your memory.
If you only need integer values, BigInteger is an option.
Study What Every Computer Scientist Should Know About Floating-Point Arithmetic, David Goldberg, 1991.
https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

Check every permutation of a number for primality

I'm working on this problem https://projecteuler.net/problem=49 .
This is the function to check every permutation of a number(4 digit) passed to it, and check them for primality, and if there are more than 2 (ie 3) print the numbers.
the output I'm getting is a never ending sequence of numbers. What am I doing wrong?
P.s- pretty sure it has to do with the repetition of digits, can't figure out how to work around it.
void checkperm(int a) {
int w, x, y, z = 0;
int count = 0;
w = a % 10;
x = (a % 100 - w) / 10;
y = (a % 1000 - (10 * x + w) / 100);
z = a - (y * 100 + x * 10 + w)/1000;
System.out.println(w+x+y+z); /*test*/
int[] data;
data = new int[] { w, x, y, z };
int[] num = new int[100];
for (int m = 0; m < 4; m++) {
for (int n = 0; n < 4; n++) {
for (int o = 0; o < 4; o++) {
for (int p = 0; p < 4; p++) {
if (true) {
int gnaw = 1000 * data[m] + 100 * data[n] + 10 * data[o] + data[p];
if (checkprime(gnaw)) {
num[count] = gnaw;
count++;
}
}
}
}
}
}
if (count > 2)
for (int h = 0; h < 4; h++) {
System.out.println(num[h]);
}
}
the way you're calculating w, x, y and z is wrong.
what it should be -
int temp = a;
w = temp%10;
temp = temp/10;
x = temp%10;
temp = temp/10;
y = temp%10;
temp = temp/10;
z = temp;
This is just logic correction from your code. Ideally all this should happen in a loop.
This will help assuming your rest of code is logically correct (which I haven't gone through).

points of intersection by determinate not working

I have unfinished code to find the points of intersection of all lines that are perpendicular. So far I have this:
import java.util.Scanner;
public class CountSquares {
public static void main(String args[]) {
Scanner scan = new Scanner(System.in);
int lines = scan.nextInt();
scan.nextLine();
double[][] lineMXYC = new double[4][lines]; // stores the slope, and x
// and y co-ordinates and c
// so the line can be
// represented as y = mx + c
double x1 = 0.0, x2 = 0.0, y1 = 0.0, y2 = 0.0;
double slope = 0.0;
for (int i = 0; i < lines; i++) {
String input = scan.nextLine();
String[] arrayOfInput = input.split(" ");
x1 = Integer.parseInt(arrayOfInput[0]);
y1 = Integer.parseInt(arrayOfInput[1]);
x2 = Integer.parseInt(arrayOfInput[2]);
y2 = Integer.parseInt(arrayOfInput[3]);
if (x1 == x2)
slope = Double.POSITIVE_INFINITY;
else
slope = (y2 - y1) / (x2 - x1);
lineMXYC[0][i] = slope;
lineMXYC[1][i] = x1;
lineMXYC[2][i] = y1;
lineMXYC[3][i] = y1 - (slope * x1);
}
for (int j = 0; j < lines - 1; j++) { //sorts the array by slopes
if (lineMXYC[0][j] > lineMXYC[0][j + 1]) {
double TEMP = lineMXYC[0][j + 1];
lineMXYC[0][j + 1] = lineMXYC[0][j];
lineMXYC[0][j] = TEMP;
}
}
double[] pointsOfIntersectionX = new double[(int) (lines * lines / 4) + 1]; //max number of points there can be
double[] pointsOfIntersectionY = new double[(int) (lines * lines / 4) + 1];
int count = 0;
for (int k = 0; k < lines; k++) {
for (int n = k; n < lines; n++) {
System.out.println(n + " " + k);
if (1 / lineMXYC[0][k] == -lineMXYC[0][n]) {
double m1 = lineMXYC[0][k];
double m2 = lineMXYC[0][n];
double c1 = lineMXYC[3][k];
double c2 = lineMXYC[3][n];
System.out.println("m1: "+m1);
System.out.println("m2: "+m2);
System.out.println("c1: "+c1);
System.out.println("c2: "+c2);
pointsOfIntersectionX[count] = (c1 - c2) / (m2 - m1); //determinate to find x co-ordinate
pointsOfIntersectionY[count] = (m2 * c1 - m1 * c2)
/ (m2 - m1);
System.out.println("The lines intersect at: ("
+ pointsOfIntersectionX[count] + ", "
+ pointsOfIntersectionY[count] + ")");
count++;
}
}
}
scan.close();
}
}
This will take in the number of lines, then two points on each line seperated by spaces. If I enter
2
3 -1 0 8
3 -1 0 -2
It works fine, finding the point (3, -1)
However, if I put in the same values reversed
2
3 -1 0 -2
3 -1 0 8
It gives me (-3.0, 6.999999999999999) which is wrong
What is going wrong with the code? I can't pinpoint where the problem comes from.
Sorting by slopes may mix your input data in your version.
If you want to swap the lines, swap all line data:
for (int j = 0; j < lines - 1; j++) { //sorts the array by slopes
if (lineMXYC[0][j] > lineMXYC[0][j + 1]) {
for (int i = 0; i < 4; i++) {
double TEMP = lineMXYC[i][j + 1];
lineMXYC[i][j + 1] = lineMXYC[i][j];
lineMXYC[i][j] = TEMP;
}
}
}
If I may give you an advice:
make a separate Line class for better design
implement the compare method or a line comparator
use some sorting algorithm, the one you use will not sort correctly for more lines, e.g. see Java Tutorials

Perlin noise - What am I doing wrong?

I just started with world generation and I've been looking for tutorials on perlin noise everywhere but sadly there are not alot to be found on Google.
The last days I followed a tutorial but I can't get my code to work.
Here is my Java method.
private static double[][] createNoise(int xn, int yn, int sps) {
int m = yn * sps;
int n = xn * sps;
double[][] u = new double[yn + 1][];
double[][] v = new double[yn + 1][];
double[][] x = new double[m][];
double[][] y = new double[m][];
double[][] z = new double[m][];
for (int i = 0; i < m; i++) {
x[i] = new double[n];
y[i] = new double[n];
z[i] = new double[n];
}
for (int i = 0; i < yn + 1; i++) {
u[i] = new double[xn + 1];
v[i] = new double[xn + 1];
}
for (int i = 0; i < xn + 1; i++) {
for (int j = 0; j < yn + 1; j++) {
u[i][j] = nextRandom();
v[i][j] = nextRandom();
}
}
double hx = xn / (n - 1);
double hy = yn / (m - 1);
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
x[i][j] = hx * j;
y[i][j] = hy * i;
}
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
int xc = (int)x[i][j];
int yc = (int)y[i][j];
if (x[i][j] % 1 == 0 && x[i][j] != 0 ) xc = xc - 1;
if (y[i][j] % 1 == 0 && y[i][j] != 0 ) yc = yc - 1;
double xr = x[i][j] - xc;
double yr = y[i][j] - yc;
double s11[] = {-xr, -yr};
double s21[] = {-xr, 1 - yr};
double s22[] = {1 - xr, 1 - yr};
double s12[] = {1 - xr, -yr};
double q11 = s11[0] * u[yc][xc] + s11[1] * v[yc][xc];
double q21 = s21[0] * u[yc + 1][xc] + s21[1] * v[yc + 1][xc];
double q22 = s22[0] * u[yc + 1][xc + 1] + s22[1] * v[yc + 1][xc + 1];
double q12 = s12[0] * u[yc][xc + 1] + s12[1] * v[yc][xc + 1];
z[i][j] = lerp(x[i][j], y[i][j], xc, xc + 1, yc, yc + 1, q11, q12, q21, q22);
}
}
return z;
}
The heightmap that the method returns sadly enough looks like this
As you can see, the first row/column is working, but after that the algorithm seems to fail.
I made sure that the method
nextRandom();
returns a float value between -1 & 1.
Thanks alot!
Thanks to user #gawi for pointing this out.
hx = xn / (n - 1);
will divide 2 integers, and most likely return 0.
You can fix this by casting a double to it:
double hx = (double)xn / (n - 1);
Then the map just works!

nested for() loops && using the "i" count from the first loop in the second so i loops just once using the value?

i am trying to not import the math class to use but i am still trying to estimate the constant "e". it is said e= 1+(1/1!)+(1/2!)+(1/3!)+(1/4!)+(1/5!)+.....
these are what i have int at the top
String userInput;
int uIp; // this converts the string into int type
double e = 2;
then i ask some questions then i check to see not zero to exit and non negative to continue
While(uIp >0){
final int endTheLoop = 15;
int factorialNumber = 1;
double e2TheUserInput=0;
for(int i = 2; i < endTheLoop; i++){
for(int j = 1; j < i; j++){
factorialNumber = ((i - 1) * factorialNumber);
}
e = (1/factorialNumber) + e;
e2TheUserInput = Math.pow(e,uIp);
}
}
You are doing integer division(but e is a double right?):
e = (1/factorialNumber) + e;
Correct that to:
e = (1.0/(double)factorialNumber) + e;
It was counting all the loops, but changes are zero according to the integer division. :)
e= 2+(0)+(0)+(0)+(0)+.....
I am not sure what your code is trying to do but if you want to compute exp(x) this is how I would do it.
public static void main(String... args) {
for (int i = -4; i <= 4; i++)
System.out.println(i + ": " + exp(i) + " cf " + Math.exp(i));
}
private static double exp(double d) {
if (d < 0)
return 1 / exp(-d);
double e = 1, term = 1;
for (int i = 1; i < 20 || term > e * 1e-16; i++) {
term *= d / i;
e += term;
}
return e;
}
For large exponents, it more efficient to evaluate the integral powers without using a taylor series.
public static final double E = 2.7182818284590452354;
private static double exp(double d) {
if (d < 0)
return 1 / exp(-d);
long num = (long) d;
double numE = 1;
double mult = E;
while (num > 0) {
if ((num & 1) != 0)
numE *= mult;
num >>>= 1;
mult *= mult;
}
double fract = d - (long) d;
double fractE = 1, term = 1;
for (int i = 1; i < 20; i++) {
term *= fract / i;
fractE += term;
}
return numE * fractE;
}

Categories

Resources