This code should compare two fitnesses, use the best one to find the solution and then it uses the best one in the next iteration. However the problem I get is that it is just using the newest fitness regardless of whether it is bigger or smaller. Can anyone help me spot if there are any mistakes in my code, thanks!
This was a little tricky to explain, so if anyone needs more clarification please ask and I'll post up my entire project, though I believe that the error has something to do with this small section of code:
public static ScalesSolution RMHC(ArrayList<Double> weights, int n, int iter) {
ScalesSolution sol = new ScalesSolution(n);
ScalesSolution oldSol = new ScalesSolution(sol.GetSol());
for (int i = 0; i < iter; i++) {
System.out.println("Iteration number: " + i);
System.out.println("Old Solution : ");
oldSol.println();
double f = oldSol.ScalesFitness(weights);
System.out.println("Old Fitness: ");
System.out.println(f);
// the new solution after copying the string from scalesolution
sol.SmallChange();
System.out.println("New Solution : ");
sol.println();
double f1 = sol.ScalesFitness(weights);
System.out.println("New Fitness: ");
System.out.println(f1);
if (oldSol.ScalesFitness(weights) > sol.ScalesFitness(weights)) {
oldSol = new ScalesSolution(sol.GetSol());
}
}
return (oldSol);
}
Here is SmallChange:
public void SmallChange() {
int n = scasol.length();
Random rand = new Random();
int p = (rand.nextInt(n));
String x;
x = scasol.substring(0, p);
if (scasol.charAt(p) == '0') {
x += '1';
} else {
x += '0';
}
x += scasol.substring(p + 1, n);
scasol = x;
}
Here is ScalesFitness and ScalesSolution:
public ScalesSolution(int n) {
scasol = RandomBinaryString(n);
}
// This is the fitness function for the Scales problem
// This function returns -1 if the number of weights is less than the size of the current solution
// Exercise 3
public static double ScalesFitness(ArrayList<Double> weights) {
int n = scasol.length(); // Assigns the length of scasol to n
double lhs = 0.0; // Initialises lhs to 0.0, type double
double rhs = 0.0; // Initialises rhs to 0.0, type double
if (n > weights.size()) // If statement, compares n and weight size
return (-1); // Returns -1 when the if statement is true
// Code goes here
for (int i = 0; i < n; i++) { // For loop which goes from i=0 to n
if (scasol.charAt(i) == '0') { // If statement which checks if the character at position i is equal to a 0
lhs += weights.get(i); // Adds weight at position i to lhs
} else { // If the character in position i is not a 0 do the following
rhs += weights.get(i); // Adds the weight at position i to rhs
}
}
return (Math.abs(lhs - rhs)); // Calculates the absolute value of lhs-rhs and returns the value
}
Related
I have implemented a function to find the trapezoid rule of a given function, the function produces poor results for
.
When I try to calculate the trapezoid rule with n < 8 it produces a value much larger than the actual area, which is unexpected, I have graphed f(x) and drawn how I believe the first few numbers of trapezoids would look, and they all should be producing less than the target area.
However, as n increases, the error becomes lower and lower and at n = 10000000 it is within a 0.001 of the solution.
private interface MathFunc {
double apply(double value);
}
private static final double A = 1;
private static final double B = 9;
public static void main(String args[]) {
MathFunc func = (x) -> Math.log(x) / Math.log(2);
double realValue = 16.98776493946568;
for(int i = 1; i <= 8; i*=2) {
double value = trapezoidRule(A, B, func, i);
System.out.println(i + " Trapezoid Summation for f(x): " + value);
double absError = Math.abs(value - realValue);
System.out.println("Abs Error: " + absError);
System.out.println("% Error: " + (absError/realValue)*100);
System.out.println();
}
}
static double trapezoidRule(double a, double b, MathFunc f, double n) {
double deltaX = (b-a)/n;
double i = 0;
double sum = 0.0;
while( i++ <= n ) {
if(i == 0 || i == n) {
sum += f.apply(a + (i*deltaX));
} else {
sum += 2 * f.apply(a + (i*deltaX));
}
}
return (deltaX * sum) / 2.0;
}
If you step through trapezoidRule for n = 1 in a debugger, you'll see that the loop is executed for i=1 and i=2. Since i=2 is treated as a midpoint, it is counted twice.
Why is the loop executed for wrong values of i? The expression i++ uses the post-increment operator, which increments the variable after returning its value. You should be using a pre-increment operator ++i, or a for loop like any sane person:
for (double i = 0; i <= n; i++) {
while( i++ <= n )
Was causing an issue, as it was doing an extra iteration.
while( i++ < n )
Produces the correct values.
The output is not showing the HCF but showing the initialized value that is 1.
package questionsOnLoops;
import java.util.Scanner;
public class hg {
public static void main(String[] args) {
Scanner srv = new Scanner(System.in);
System.out.print("Enter the first number: ");
int n1 = srv.nextInt(); //first number
System.out.println("Enter the second number: ");
int n2 = srv.nextInt(); //second number
int HCF=1; // Highest Common factor
int s; //smaller of two number
s = Math.min(n1, n2);
for(int i = s; i <= 1 ; i--) {
if(n1%i==0&&n2%i==0) {
HCF=i;
break;
}
}
System.out.println(HCF);
}
}
for(i = 1; i <= a || i <= b; i++) {
if( a%i == 0 && b%i == 0 )
hcf = i;
}
Use this logic. here a is the first number and b is the second.
Your code is never executing the "for" loop because you set i=s and i will never be i<=1...
Change to i>=1 and you're good to go
You have just to change your operator in your 'for' loop.
for(int i = s; i >= 1 ; i--) {
Because in your code you loop while i is less than 1. But in your inizialization i is equal to s. So you never enter in the 'for' loop and your HCF is the default value of your HCF variable which is 1.
For your culture if you want an optimized way to calculate the HCF, you can use the Euclidean algorithm which reduce drastically the number of operation. Because you transform several division and condition into a few Euclidean division.
Here an exemple
public int hcf(int m, int n) {
// the remainder of the Euclidean division
int r = 0;
// The algorithm says "the HCF of m and n is the last non-zero remainder"
while(n != 0) {
r = m % n;
m = n;
n = r;
}
return m;
}
I wrote a simple program to calculate the maximum number of times square root can be calculated on a number , input is an interval from num1 to num2
eg:
if the input is (1,20), answer is 2, since square root of 16 is 4 , and square root of 4 is 2 .
int max = 0;
for (int i = num1; i <= num2; i++) {
boolean loop = true;
int count = 0;
int current = i;
if (i == 1) {
count++;
} else {
while (loop) {
double squareRoot = Math.sqrt(current);
if (isCurrentNumberPerfectSquare(squareRoot)) {
count++;
current = (int) squareRoot;
} else {
loop = false;
}
}
}
if (count > max) {
max = count;
}
}
return max;
static boolean isCurrentNumberPerfectSquare(double number) {
return ((number - floor(number)) == 0);
}
I get the answer, but was wondering wether this can be improved using some mathematical way ?
Any suggestions ?
To avoid more confusion here my final answer to this topic.
A combination of both previously mentioned approaches.
What 'Parameswar' is looking for is the largest perfect square formed by the lowest base.
Step 1 -
To get that calculate the largest possible perfect square based on your num2 value.
If it is outside your range, you have no perfect square within.
Step 2 -
If it is within your range, you have to check all perfect square formed by a lower base value with a higher number of times.
Step 3 -
If you find one that is within your range, replace your result with the new result and proceed to check lower values. (go back to Step 2)
Step 4 -
Once the value you check is <= 2 you have already found the answer.
Here some sample implementation:
static class Result {
int base;
int times;
}
static boolean isCurrentNumberPerfectSquare(double number) {
return ((number - Math.floor(number)) == 0);
}
private static int perfectSquare(int base, int times) {
int value = base;
for (int i = times; i > 0; i--) {
value = (int) Math.pow(base, 2);
}
return value;
}
private static Result calculatePerfectSquare(int perfectSquare) {
Result result = new Result();
result.base = (int) Math.sqrt(perfectSquare);
result.times = 1;
while (result.base > 2 && isCurrentNumberPerfectSquare(Math.sqrt(result.base))) {
result.base = (int) Math.sqrt(result.base);
result.times += 1;
}
System.out.println(perfectSquare + " -> " + result.base + " ^ " + result.times);
return result;
}
static int maxPerfectSquares(int num1, int num2) {
int largestPerfectSqr = (int) Math.pow(Math.floor(Math.sqrt(num2)), 2);
if (largestPerfectSqr < num1) {
return 0;
}
Result result = calculatePerfectSquare(largestPerfectSqr);
int currentValue = result.base;
while (currentValue > 2) {
// check lower based values
currentValue--;
int newValue = perfectSquare(currentValue, result.times + 1);
if (newValue >= num1 && newValue < num2) {
result = calculatePerfectSquare(newValue);
currentValue = result.base;
}
}
return result.times;
}
Edit - My assumption is incorrect. Refer to the answer provided by "second".
You can remove the outer loop, num2 can be directly used to determine the number with the maximum number of recursive square roots.
requiredNumber = square(floor(sqrt(num2)));
You just need to check to see if the requiredNumber exists in the range [num1, num2] after finding it.
So the refactoring code would look something like this,
int requiredNumber = Math.pow(floor(Math.sqrt(num2)),2);
int numberOfTimes=0;
if(requiredNumber>=num1) {
if (requiredNumber == 1) {
numberOfTimes=1;
} else{
while (isCurrentNumberPerfectSquare(requiredNumber)) {
numberOfTimes++;
}
}
}
Edit 4: for a more optimal approach check my other answer.
I just leave this here if anybody wants to try to follow my thought process ;)
Edit 3:
Using prime numbers is wrong, use lowest non perfect square instead
Example [35,37]
Edit 2:
Now that I think about it there is a even better approach, especially if you assume that num1 and num2 cover a larger range.
Start with the lowest prime number 'non perfect square' and
calculate the maximum perfect square that fits into your range.
If you have found one, you are done.
If not continue with the next prime number 'non perfect square'.
As a example that works well enough for smaller ranges:
I think you can improve the outerloop. There is no need to test every number.
If you know the smallest perfect square, you can just proceed to the next perfect square in the sequence.
For example:
[16, 26]
16 -> 4 -> 2 ==> 2 perfect squares
No neeed to test 17 to 24
25 -> 5 ==> 1 perfect square
and so on ...
#Chrisvin Jem
Your assumption is not correct, see example above
Edit:
Added some code
static int countPerfectSquares(int current) {
int count = 0;
while (true) {
double squareRoot = Math.sqrt(current);
if (isCurrentNumberPerfectSquare(squareRoot)) {
count++;
current = (int) squareRoot;
} else {
return count;
}
}
}
static boolean isCurrentNumberPerfectSquare(double number) {
return ((number - Math.floor(number)) == 0);
}
static int numPerfectSquares(int num1, int num2) {
int max = 0;
if (num1 == 1) {
max = 1;
}
int sqr = Math.max(2, (int) Math.floor(Math.sqrt(num1)));
int current = (int) Math.pow(sqr, 2);
if (current < num1) {
current = (int) Math.pow(++sqr, 2);
}
while (current <= num2) {
max = Math.max(countPerfectSquares(current), max);
current = (int) Math.pow(++sqr, 2);
}
return max;
}
Note: Updated on 06/17/2015. Of course this is possible. See the solution below.
Even if anyone copies and pastes this code, you still have a lot of cleanup to do. Also note that you will have problems inside the critical strip from Re(s) = 0 to Re(s) = 1 :). But this is a good start.
import java.util.Scanner;
public class NewTest{
public static void main(String[] args) {
RiemannZetaMain func = new RiemannZetaMain();
double s = 0;
double start, stop, totalTime;
Scanner scan = new Scanner(System.in);
System.out.print("Enter the value of s inside the Riemann Zeta Function: ");
try {
s = scan.nextDouble();
}
catch (Exception e) {
System.out.println("You must enter a positive integer greater than 1.");
}
start = System.currentTimeMillis();
if (s <= 0)
System.out.println("Value for the Zeta Function = " + riemannFuncForm(s));
else if (s == 1)
System.out.println("The zeta funxtion is undefined for Re(s) = 1.");
else if(s >= 2)
System.out.println("Value for the Zeta Function = " + getStandardSum(s));
else
System.out.println("Value for the Zeta Function = " + getNewSum(s));
stop = System.currentTimeMillis();
totalTime = (double) (stop-start) / 1000.0;
System.out.println("Total time taken is " + totalTime + " seconds.");
}
// Standard form the the Zeta function.
public static double standardZeta(double s) {
int n = 1;
double currentSum = 0;
double relativeError = 1;
double error = 0.000001;
double remainder;
while (relativeError > error) {
currentSum = Math.pow(n, -s) + currentSum;
remainder = 1 / ((s-1)* Math.pow(n, (s-1)));
relativeError = remainder / currentSum;
n++;
}
System.out.println("The number of terms summed was " + n + ".");
return currentSum;
}
public static double getStandardSum(double s){
return standardZeta(s);
}
//New Form
// zeta(s) = 2^(-1+2 s)/((-2+2^s) Gamma(1+s)) integral_0^infinity t^s sech^2(t) dt for Re(s)>-1
public static double Integrate(double start, double end) {
double currentIntegralValue = 0;
double dx = 0.0001d; // The size of delta x in the approximation
double x = start; // A = starting point of integration, B = ending point of integration.
// Ending conditions for the while loop
// Condition #1: The value of b - x(i) is less than delta(x).
// This would throw an out of bounds exception.
// Condition #2: The value of b - x(i) is greater than 0 (Since you start at A and split the integral
// up into "infinitesimally small" chunks up until you reach delta(x)*n.
while (Math.abs(end - x) >= dx && (end - x) > 0) {
currentIntegralValue += function(x) * dx; // Use the (Riemann) rectangle sums at xi to compute width * height
x += dx; // Add these sums together
}
return currentIntegralValue;
}
private static double function(double s) {
double sech = 1 / Math.cosh(s); // Hyperbolic cosecant
double squared = Math.pow(sech, 2);
return ((Math.pow(s, 0.5)) * squared);
}
public static double getNewSum(double s){
double constant = Math.pow(2, (2*s)-1) / (((Math.pow(2, s)) -2)*(gamma(1+s)));
return constant*Integrate(0, 1000);
}
// Gamma Function - Lanczos approximation
public static double gamma(double s){
double[] p = {0.99999999999980993, 676.5203681218851, -1259.1392167224028,
771.32342877765313, -176.61502916214059, 12.507343278686905,
-0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7};
int g = 7;
if(s < 0.5) return Math.PI / (Math.sin(Math.PI * s)*gamma(1-s));
s -= 1;
double a = p[0];
double t = s+g+0.5;
for(int i = 1; i < p.length; i++){
a += p[i]/(s+i);
}
return Math.sqrt(2*Math.PI)*Math.pow(t, s+0.5)*Math.exp(-t)*a;
}
//Binomial Co-efficient - NOT CURRENTLY USING
/*
public static double binomial(int n, int k)
{
if (k>n-k)
k=n-k;
long b=1;
for (int i=1, m=n; i<=k; i++, m--)
b=b*m/i;
return b;
} */
// Riemann's Functional Equation
// Tried this initially and utterly failed.
public static double riemannFuncForm(double s) {
double term = Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s);
double nextTerm = Math.pow(2, (1-s))*Math.pow(Math.PI, (1-s)-1)*(Math.sin((Math.PI*(1-s))/2))*gamma(1-(1-s));
double error = Math.abs(term - nextTerm);
if(s == 1.0)
return 0;
else
return Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s)*standardZeta(1-s);
}
}
Ok well we've figured out that for this particular function, since this form of it isn't actually a infinite series, we cannot approximate using recursion. However the infinite sum of the Riemann Zeta series (1\(n^s) where n = 1 to infinity) could be solved through this method.
Additionally this method could be used to find any infinite series' sum, product, or limit.
If you execute the code your currently have, you'll get infinite recursion as 1-(1-s) = s (e.g. 1-s = t, 1-t = s so you'll just switch back and forth between two values of s infinitely).
Below I talk about the sum of series. It appears you are calculating the product of the series instead. The concepts below should work for either.
Besides this, the Riemann Zeta Function is an infinite series. This means that it only has a limit, and will never reach a true sum (in finite time) and so you cannot get an exact answer through recursion.
However, if you introduce a "threshold" factor, you can get an approximation that is as good as you like. The sum will increase/decrease as each term is added. Once the sum stabilizes, you can quit out of recursion and return your approximate sum. "Stabilized" is defined using your threshold factor. Once the sum varies by an amount less than this threshold factor (which you have defined), your sum has stabilized.
A smaller threshold leads to a better approximation, but also longer computation time.
(Note: this method only works if your series converges, if it has a chance of not converging, you might also want to build in a maxSteps variable to cease execution if the series hasn't converged to your satisfaction after maxSteps steps of recursion.)
Here's an example implementation, note that you'll have to play with threshold and maxSteps to determine appropriate values:
/* Riemann's Functional Equation
* threshold - if two terms differ by less than this absolute amount, return
* currSteps/maxSteps - if currSteps becomes maxSteps, give up on convergence and return
* currVal - the current product, used to determine threshold case (start at 1)
*/
public static double riemannFuncForm(double s, double threshold, int currSteps, int maxSteps, double currVal) {
double nextVal = currVal*(Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s)); //currVal*term
if( s == 1.0)
return 0;
else if ( s == 0.0)
return -0.5;
else if (Math.abs(currVal-nextVal) < threshold) //When a term will change the current answer by less than threshold
return nextVal; //Could also do currVal here (shouldn't matter much as they differ by < threshold)
else if (currSteps == maxSteps)//When you've taken the max allowed steps
return nextVal; //You might want to print something here so you know you didn't converge
else //Otherwise just keep recursing
return riemannFuncForm(1-s, threshold, ++currSteps, maxSteps, nextVal);
}
}
This is not possible.
The functional form of the Riemann Zeta Function is --
zeta(s) = 2^s pi^(-1+s) Gamma(1-s) sin((pi s)/2) zeta(1-s)
This is different from the standard equation in which an infinite sum is measured from 1/k^s for all k = 1 to k = infinity. It is possible to write this as something similar to --
// Standard form the the Zeta function.
public static double standardZeta(double s) {
int n = 1;
double currentSum = 0;
double relativeError = 1;
double error = 0.000001;
double remainder;
while (relativeError > error) {
currentSum = Math.pow(n, -s) + currentSum;
remainder = 1 / ((s-1)* Math.pow(n, (s-1)));
relativeError = remainder / currentSum;
n++;
}
System.out.println("The number of terms summed was " + n + ".");
return currentSum;
}
The same logic doesn't apply to the functional equation (it isn't a direct sum, it is a mathematical relationship). This would require a rather clever way of designing a program to calculate negative values of Zeta(s)!
The literal interpretation of this Java code is ---
// Riemann's Functional Equation
public static double riemannFuncForm(double s) {
double currentVal = (Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s));
if( s == 1.0)
return 0;
else if ( s == 0.0)
return -0.5;
else
System.out.println("Value of next value is " + nextVal(1-s));
return currentVal;//*nextVal(1-s);
}
public static double nextVal(double s)
{
return (Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s));
}
public static double getRiemannSum(double s) {
return riemannFuncForm(s);
}
Testing on three or four values shows that this doesn't work. If you write something similar to --
// Riemann's Functional Equation
public static double riemannFuncForm(double s) {
double currentVal = Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s); //currVal*term
if( s == 1.0)
return 0;
else if ( s == 0.0)
return -0.5;
else //Otherwise just keep recursing
return currentVal * nextVal(1-s);
}
public static double nextVal(double s)
{
return (Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s));
}
I was misinterpretation how to do this through mathematics. I will have to use a different approximation of the zeta function for values less than 2.
I think I need to use a different form of the zeta function. When I run the entire program ---
import java.util.Scanner;
public class Test4{
public static void main(String[] args) {
RiemannZetaMain func = new RiemannZetaMain();
double s = 0;
double start, stop, totalTime;
Scanner scan = new Scanner(System.in);
System.out.print("Enter the value of s inside the Riemann Zeta Function: ");
try {
s = scan.nextDouble();
}
catch (Exception e) {
System.out.println("You must enter a positive integer greater than 1.");
}
start = System.currentTimeMillis();
if(s >= 2)
System.out.println("Value for the Zeta Function = " + getStandardSum(s));
else
System.out.println("Value for the Zeta Function = " + getRiemannSum(s));
stop = System.currentTimeMillis();
totalTime = (double) (stop-start) / 1000.0;
System.out.println("Total time taken is " + totalTime + " seconds.");
}
// Standard form the the Zeta function.
public static double standardZeta(double s) {
int n = 1;
double currentSum = 0;
double relativeError = 1;
double error = 0.000001;
double remainder;
while (relativeError > error) {
currentSum = Math.pow(n, -s) + currentSum;
remainder = 1 / ((s-1)* Math.pow(n, (s-1)));
relativeError = remainder / currentSum;
n++;
}
System.out.println("The number of terms summed was " + n + ".");
return currentSum;
}
public static double getStandardSum(double s){
return standardZeta(s);
}
// Riemann's Functional Equation
public static double riemannFuncForm(double s, double threshold, double currSteps, int maxSteps) {
double term = Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s);
//double nextTerm = Math.pow(2, (1-s))*Math.pow(Math.PI, (1-s)-1)*(Math.sin((Math.PI*(1-s))/2))*gamma(1-(1-s));
//double error = Math.abs(term - nextTerm);
if(s == 1.0)
return 0;
else if (s == 0.0)
return -0.5;
else if (term < threshold) {//The recursion will stop once the term is less than the threshold
System.out.println("The number of steps is " + currSteps);
return term;
}
else if (currSteps == maxSteps) {//The recursion will stop if you meet the max steps
System.out.println("The series did not converge.");
return term;
}
else //Otherwise just keep recursing
return term*riemannFuncForm(1-s, threshold, ++currSteps, maxSteps);
}
public static double getRiemannSum(double s) {
double threshold = 0.00001;
double currSteps = 1;
int maxSteps = 1000;
return riemannFuncForm(s, threshold, currSteps, maxSteps);
}
// Gamma Function - Lanczos approximation
public static double gamma(double s){
double[] p = {0.99999999999980993, 676.5203681218851, -1259.1392167224028,
771.32342877765313, -176.61502916214059, 12.507343278686905,
-0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7};
int g = 7;
if(s < 0.5) return Math.PI / (Math.sin(Math.PI * s)*gamma(1-s));
s -= 1;
double a = p[0];
double t = s+g+0.5;
for(int i = 1; i < p.length; i++){
a += p[i]/(s+i);
}
return Math.sqrt(2*Math.PI)*Math.pow(t, s+0.5)*Math.exp(-t)*a;
}
//Binomial Co-efficient
public static double binomial(int n, int k)
{
if (k>n-k)
k=n-k;
long b=1;
for (int i=1, m=n; i<=k; i++, m--)
b=b*m/i;
return b;
}
}
I notice that plugging in zeta(-1) returns -
Enter the value of s inside the Riemann Zeta Function: -1
The number of steps is 1.0
Value for the Zeta Function = -0.0506605918211689
Total time taken is 0.0 seconds.
I knew that this value was -1/12. I checked some other values with wolfram alpha and observed that --
double term = Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s);
Returns the correct value. It is just that I am multiplying this value every time by zeta(1-s). In the case of Zeta(1/2), this will always multiply the result by 0.99999999.
Enter the value of s inside the Riemann Zeta Function: 0.5
The series did not converge.
Value for the Zeta Function = 0.999999999999889
Total time taken is 0.006 seconds.
I am going to see if I can replace the part for --
else if (term < threshold) {//The recursion will stop once the term is less than the threshold
System.out.println("The number of steps is " + currSteps);
return term;
}
This difference is the error between two terms in the summation. I may not be thinking about this correctly, it is 1:16am right now. Let me see if I can think better tomorrow ....
I am a beginner in Java and currently going through the "how to think like a computer scientist" beginners book. I am stuck with a problem in the iteration chapter. Could anyone please point me in the right direction?
When I use math.exp, I get an answer that is completely different from the answer my code obtains.
Note, it's not homework.
Here's the question:
One way to calculate ex is to use the infinite series expansion
ex = 1 + x + x2 /2! + x3/3! + x4/4! +...
If the loop variable is named i, then the ith term is xi/i!.
Write a method called myexp that adds up the first n terms of this
series.
So here's the code:
public class InfiniteExpansion {
public static void main(String[] args){
Scanner infinite = new Scanner(System.in);
System.out.println("what is the value of X?");
double x = infinite.nextDouble();
System.out.println("what is the power?");
int power = infinite.nextInt();
System.out.println(Math.exp(power));//for comparison
System.out.println("the final value of series is: "+myExp(x, power));
}
public static double myExp(double myX, double myPower){
double firstResult = myX;
double denom = 1;
double sum =myX;
for(int count =1;count<myPower;count++){
firstResult = firstResult*myX;//handles the numerator
denom = denom*(denom+1);//handles the denominator
firstResult = firstResult/denom;//handles the segment
sum =sum+firstResult;// adds up the different segments
}
return (sum+1);//gets the final result
}
}
The assignment denom = denom*(denom+1) is going to give a sequence as follows: 1, 1*2=2, 2*3=6, 6*7=42, 42*43=...
But you want denom = denom*count.
Let's say in general we just want to print the first n factorials starting with 1!: 1!, 2!, 3!, ..., n!. At the kth term, we take the k-1th term and multiply by k. That would be computing k! recursively on the previous term. Concrete examples: 4! is 3! times 4, 6! is 5! times 6.
In code, we have
var n = 7;
var a = 1;
for (int i = 1; i <= n; i++ ) {
a = a*i; // Here's the recursion mentioned above.
System.out.println(i+'! is '+a);
}
Try running the above and compare to see what you get with running the following:
var n = 7;
var a = 1;
for (int i = 1; i <= n; i++ ) {
a = a*(a+1);
System.out.println('Is '+i+'! equal to '+a+'?');
}
There are several errors here:
firstResult should start from 1, so that it goes 1+x+x^2 instead of 1+x^2+x^3
As timctran stated you are not calculating the factorial in a correct way.
To wrap up you can simplify your operations to:
firstResult = firstResult * myX / (count+1);
sum += firstResult;
Edit:
- I ran the code and saw that Math.exp(power) is printed instead of Math.exp(x)
- My first item is wrong since sum is initialized to myX.
Why make it complicated? I tried a solution and it looks like this:
//One way to calculate ex is to use the infinite series expansion
//ex = 1 + x + x2 /2! + x3/3! + x4/4! +...
//If the loop variable is named i, then the ith term is xi/i!.
//
//Write a method called myexp that adds up the first n terms of this series.
import java.util.Scanner;
public class InfiniteExpansion2 {
public static void main(String[] args) {
Scanner infinite = new Scanner(System.in);
System.out.println("what is the value of X?");
double x = infinite.nextDouble();
System.out.println("what is the value of I?"); // !
int power = infinite.nextInt();
System.out.println(Math.exp(power));//for comparison
System.out.println("the final value of series is: " + myCalc(x, power));
}
public static double fac(double myI) {
if (myI > 1) {
return myI * fac(myI - 1);
} else {
return 1;
}
}
public static double exp(double myX, double myE) {
double result;
if (myE == 0) {
result = 1;
} else {
result = myX;
}
for (int i = 1; i < myE; i++) {
result *= myX;
}
return result;
}
public static double myCalc(double myX, double myI) {
double sum = 0;
for (int i = 0; i <= myI; i++) { // x^0 is 1
sum += (exp(myX, i) / fac(i));
}
return sum;
}
}
If you want to think like an engineer, I'd do it like this:
keep it simple
break it into pieces
stick closely to the task (like I named the var myI, not myPower - seems clearer to me, for a start - that way you won't get confused)
I hope you like it!
I tried a solution and it looks like this:
public class Fact {
public int facto(int n){
if(n==0)
return 1;
else
return n*facto(n-1);
}
}
}
import java.util.Scanner;
public class Ex {
public static void main(String[] args){
Fact myexp=new Fact();
Scanner input=new Scanner(System.in);
int n=1;
double e=1,i=0,x;
int j=1;
System.out.println("Enter n: ");
n=input.nextInt();
System.out.println("Enter x: ");
x=input.nextDouble();
while(j<=n)
{
int a=myexp.facto(j);
double y=Math.pow(x,j)/(double)a;
i=i+y;
++j;
}
e=e+i;
System.out.println("e^x= "+ e);
}
}