Multiplying and Dividing by Two - java

Why are these two snippets of code giving two different results?
double sum = 1.0;
double xSqFour = x * x / 4;
for (int i = 48; i > 1; i-=2) {
sum = 1.0 + (xSqFour / ((i/2) * (i/2))) * sum;
}
return sum;
and
double sum = 1.0;
double xSqFour = x * x / 4;
for (int i = 24; i > 1; i--) {
sum = 1.0 + (xSqFour / (i * i)) * sum;
}
return sum;

You have a bounds error on your second loop. It should be i > 0. The first loop has i > 1, but it also divides i by 2. 1 / 2 == 0, so it should be i > 0 in the second loop.

Related

Simpson's double integral won't work in 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.

Do-While iteration approach determine by threshold

I have a question using Java do-while loop to determine when to stop by a threshold (MinRevChange in the code).
The larger loop will stop when the value difference between 2 closest data points is below the threshold (DfDi < MinRevChange); and the loop within it will stop when Q is greater than n (30 in this example).
private static int OBMethod33(double mean, double MinRevChange) {
double RmRev = 399;
double BenchPrice = 486;
int n = 30;
int i = 0;
double Fcurr = 0;
double Fopt = 0;
double Fprev = 0;
double DfDi = 999999;
do {
Fcurr = 0;
int Q = 0;
do {
Fcurr = Fcurr
+ RmRev * (Math.pow(mean, Q) * Math.exp(-mean) / factorialRecursive(Q)) * Math.max(Q - i, 0)
+ BenchPrice * (Math.pow(mean, Q) * Math.exp(-mean) / factorialRecursive(Q))
* Math.max(i - Q, 0);
Q++;
} while (Q <= n);
DfDi = Math.abs(Fcurr - Fprev);
Fopt = Fcurr;
Fprev = Fcurr;
i++;
} while ((i <= 10) && (DfDi >= MinRevChange));
return i - 1;
}
private static long factorialRecursive(int i) {
if (i < 0) {
return -1;
}
if (i == 0) {
return 1;
}
if (i < 2)
return i * 1;
return i * factorialRecursive(i - 1);
}
Based on Poisson Distribution pmf function: Poisson Distribution
which is the code (Math.pow(mean, Q) * Math.exp(-mean) / factorialRecursive(Q))
As Q increases to n, 'Fcurr' will be added for each Q.
DfDi is calculated by deducting the value of two 'i's: 'Fcurr' and 'Fprev'.
The second function returns factorial of a number i! = 1 * 2 * ... * i; used to calculate Poisson Distribution pmf.
Given an example of (mean, MinRevChange) = (6.2, 250) it returns 10;
while I validated the example and function using SAS, it should return 5.
I think within the first function, it seems the 'DfDi >= MinRevChange' condition is not used; How can I modify it? Thanks!
The following code works:
private static int OBMethod33(double mean, double MinRevChange) {
double RmRev = 399;
double BenchPrice = 486;
int n = 30;
int i = 0;
double Fcurr = 0;
double Fopt = 0;
double Fprev = 0;
double DfDi = 999999;
do {
Fcurr = 0;
int Q = 0;
do {
Fcurr = Fcurr
+ RmRev * (Math.pow(mean, Q) * Math.exp(-mean) / factorialRecursive(Q)) * Math.max(Q - i, 0)
+ BenchPrice * (Math.pow(mean, Q) * Math.exp(-mean) / factorialRecursive(Q))
* Math.max(i - Q, 0);
Q++;
} while (Q <= n);
DfDi = Math.abs(Fcurr - Fprev);
Fopt = Fcurr;
Fprev = Fcurr;
i++;
// This line added to print out the result after each iteration;
System.out.println("DfDi = " + DfDi + " :: Fcurr = " + Fcurr);
} while ((i <= 10) && (DfDi >= MinRevChange));
return i - 1;
}
private static long factorialRecursive(int i) {
if (i < 0) {
return -1;
}
if (i == 0) {
return 1;
}
if (i < 2)
return i * 1;
return i * factorialRecursive(i - 1);
It works by setting value pairs of (mean, MinRevChange).
Thanks!

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

How to split an integer into individual digits and then square each number?

I want to split an integer into digits and then raise each number to the power 2 and print that out. This is what I have:
int n = 666;
String number = String.valueOf(n);
for (int i = 0; i < number.length(); i++) {
int j = Character.digit(number.charAt(i), 10);
Math.pow(j, 2);
System.out.println(j);
}
The output is only the 666 number.
What is it I'm doing wrong?
Math.pow(j, 2) doesn't modify j, it returns a new value. You should capture the output of Math.pow to a variable and print that
If you want to print sq of individual digits.
int num = 666;
String number = String.valueOf(num);
for (int i = 0; i < number.length(); i++) {
int j = Character.digit(number.charAt(i), 10);
int res = (int) Math.pow((double) j, (double) 2);
System.out.println("digit: " + res);
}
int m = n;
while (m > 0)
{
int digit = m % 10;
System.out.printf("%d\n", Math.pow(digit, 2));
m /= 10;
}
Is this what you want?
Due to Andreas comment which said the order is reversed, I changed the code:
int length = number.length();
for (int i = length - 1; i >= 0; i--)
{
int divisor = (int) Math.pow(10, i);
int digit = n % divisor;
System.out.printf("%d\n", Math.pow(digit, 2));
}
Also I could have written it as:
int length = number.length();
int divisor = (int) Math.pow(10, length - 1);
while (divisor > 0)
{
int digit = n % divisor;
System.out.printf("%d\n", Math.pow(digit, 2));
divisor /= 10;
}
Your code isn't working because you don't actually use the return value of Math.pow().
Math.pow(x, 2) is one way to raise a number to the power of 2, but it is floating-point math, not integer math. Power of 2 means to multiply the number by itself, so x * x is much better.
int number = 299792458; // Speed of light in m/s
for (char ch : Integer.toString(number).toCharArray()) {
int digit = ch - '0';
System.out.println(digit * digit);
}
Or using Java 8 streams:
int number = 299792458; // Speed of light in m/s
Integer.toString(number)
.chars()
.map(c -> (c - '0') * (c - '0'))
.forEach(System.out::println);
OUTPUT
4
81
81
49
81
4
16
25
64

Java - Simpson's method and error

I am writing a Java program for Simpson's method. The basic program works as expected, although I cannot get the (absolute) error part to work.
I think I need to reference my while (absError < 0.000001) loop differently. What am I doing wrong?
First try
public static double function(double x, double s) {
double sech = 1 / Math.cosh(x); // Hyperbolic cosecant
double squared = Math.pow(sech, 2);
return ((Math.pow(x, s)) * squared);
}
// Simpson's rule - Approximates the definite integral of f from a to b.
public static double SimpsonsRule(double a, double b, double s, int n) {
double dx, x, sum4x, sum2x;
double absError = 1.0;
double simpson = 0.0;
double simpson2 = 0.0;
dx = (b-a) / n;
sum4x = 0.0;
sum2x = 0.0;
// 4/3 terms
for (int i = 1; i < n; i += 2) {
x = a + i * dx;
sum4x += function(x,s);
}
// 2/3 terms
for (int i = 2; i < n-1; i += 2) {
x = a + i * dx;
sum2x += function(x,s);
}
// Compute the integral approximation.
simpson = function(a,s) + function(a,b);
simpson = (dx / 3)*(simpson + 4 * sum4x + 2 * sum2x);
while ( absError < 0.000001)
{
simpson2 = SimpsonsRule(a, b, s, n);
absError = Math.abs(simpson2 - simpson) / 15;
simpson = simpson2;
n++;
}
System.out.println("Number of intervals is " + n + ".");
return simpson2;
}
This doesn't work since I did not write
simpson2 = SimpsonsRule(a, b, s, n);
correctly.
I tried doing this a second way, but the solution ultimately also fails.
public static double function(double x, double s) {
double sech = 1 / Math.cosh(x); // Hyperbolic cosecant
double squared = Math.pow(sech, 2);
return ((Math.pow(x, s)) * squared);
}
// Simpson's rule - Approximates the definite integral of f from a to b.
public static double SimpsonsRule(double a, double b, double s, int n) {
double dx, x, sum4x, sum2x;
double absError = 1.0;
double simpson = 0.0;
double simpson2 = 0.0;
dx = (b-a) / n;
sum4x = 0.0;
sum2x = 0.0;
// 4/3 terms
for (int i = 1; i < n; i += 2) {
x = a + i * dx;
sum4x += function(x,s);
}
// 2/3 terms
for (int i = 2; i < n-1; i += 2) {
x = a + i * dx;
sum2x += function(x,s);
}
// Compute the integral approximation.
simpson = function(a,s) + function(a,b);
simpson = (dx / 3)*(simpson + 4 * sum4x + 2 * sum2x);
while ( absError < 0.000001)
{
n++;
dx = (b-a) / n;
// 4/3 terms
for (int i = 1; i < n; i += 2) {
x = a + i * dx;
sum4x += function(x,s);
}
// 2/3 terms
for (int i = 2; i < n-1; i += 2) {
x = a + i * dx;
sum2x += function(x,s);
}
simpson = function(a,s) + function(a,b);
simpson2 = (dx / 3)*(simpson + 4 * sum4x + 2 * sum2x);
absError = Math.abs(simpson2 - simpson) / 15;
simpson = simpson2;
}
System.out.println("Number of intervals is " + n + ".");
return simpson2;
}
I need to write the while loop differently. What is wrong with the way the error is referenced inside the while loop?
The java code up until
while ( absError < 0.000001)
{
simpson2 = SimpsonsRule(a, b, s, n);
absError = Math.abs(simpson2 - simpson) / 15;
simpson = simpson2;
n++;
}
System.out.println("Number of intervals is " + n + ".");
return simpson2;
Works fine and correctly calculates Simpson's method.
Looks like your Simpson's method implementation is not converging. The easiest thing you can do to avoid infinite cycle in while - you have to add another condition - maximum number of iterations.
Something like that:
int n = 0;
while (error < ACCURACY && n++ < MAX_ITERATIONS) {
// while body
}
where ACCURACY is 0.000001 in your case (or 1e-6) and MAX_ITERATIONS is an integer constant, for example 100000 or 1e+6.
Why your algorithm is not converging - this is another question - look carefully on your formulas - use debugging tools. Good luck!
I fixed it. Thanks for your help.
// Simpson's rule - Approximates the definite integral of f from a to b.
public static double SimpsonsRule(double a, double b, double s, int n) {
double simpson, dx, x, sum4x, sum2x;
dx = (b-a) / n;
sum4x = 0.0;
sum2x = 0.0;
// 4/3 terms
for (int i = 1; i < n; i += 2) {
x = a + i * dx;
sum4x += function(x,s);
}
// 2/3 terms
for (int i = 2; i < n-1; i += 2) {
x = a + i * dx;
sum2x += function(x,s);
}
// Compute the integral approximation.
simpson = function(a,s) + function(a,b);
simpson = (dx / 3)*(simpson + 4 * sum4x + 2 * sum2x);
return simpson;
}
// Handles the error for for f(x) = t^s * sech(t)^2. The integration is
// done from 0 to 100.
// Stop Simspson's Method when the relative error is less than 1 * 10^-6
public static double SimpsonError(double a, double b, double s, int n)
{
double futureVal;
double absError = 1.0;
double finalValueOfN;
double numberOfIterations = 0.0;
double currentVal = SimpsonsRule(a,b,s,n);
while (absError / currentVal > 0.000001) {
n = 2*n;
futureVal = SimpsonsRule(a,b,s,n);
absError = Math.abs(futureVal - currentVal) / 15;
currentVal = futureVal;
}
// Find the number of iterations. N starts at 8 and doubles every iteration.
finalValueOfN = n / 8;
while (finalValueOfN % 2 == 0) {
finalValueOfN = finalValueOfN / 2;
numberOfIterations++;
}
System.out.println("The number of iterations is " + numberOfIterations + ".");
return currentVal;
}

Categories

Resources