Can anybody tell me why this code doesn't work? I'm trying to implement a sinus-function with a given limitation of precision (by the error-variable).
Certain details about the calculation are given here: https://en.wikipedia.org/wiki/Taylor_series
berechnePot calculates the potence
berechneFak calculates the faculty
berechneVZW calculates the pre sign (plus or minus)
I don't get the point, why the function is calculating that slow.
public class Sinus {
public static double sinus(double x) {
double error = 0.001;
double summand = 0;
double sum = 0;
int k = 0;
do {
double pot = 0;
double fak = 0;
pot = berechnePot(x, k);
fak = berechneFak(k);
summand = pot / fak;
berechneVZW(summand, k);
sum += summand;
k++;
} while (abs(summand) > error);
return sum;
}
public static double abs(double value) {
if (value < 0) return -value;
else return value;
}
public static double berechneVZW(double value, int k) {
if (k % 2 == 0) {
return value;
} else {
return value *= (-1);
}
}
public static double berechnePot(double x, double k) {
double pot = 0;
pot += x;
for (int i = 0; i <= k; i++) {
pot *= (x * x);
}
return pot;
}
public static double berechneFak(int k) {
double fak = 1;
if (k == 0) {
return 1;
} else {
for (int i = 0; i <= k; k++) {
fak *= (2 * i + 1);
}
}
return fak;
}
}
Finally i got to the right solution..
I hope that the new structure helps you to better understand my implementation better.
Thanks for all your help!
public class Sinus {
public static double sinus(double x) {
double error = 0.00001;
double summand = 0;
double result = 0;
double fak = 0;
int k = 0;
do {
double pot = 0;
pot = calcNumeratorPotency(x, k);
fak = calcDenumeratorFaculty(k);
summand = pot / fak;
summand = definePreSign(summand, k);
result += summand;
k++;
} while (absoluteValue(summand) > error);
return result;
}
public static double absoluteValue(double value) {
if (value < 0)
return -value;
else
return value;
}
public static double definePreSign(double value, int k) {
if (k % 2 == 0) {
return value;
} else {
return value * (-1);
}
}
public static double calcNumeratorPotency(double x, double k) {
double pot = x;
for (int i = 0; i < 2 * k; i++) {
pot *= x;
}
return pot;
}
public static double calcDenumeratorFaculty(int k) {
double fak = 1;
if (k == 0) {
return 1;
} else {
for (int i = 1; i <= (2 * k + 1); i++) {
fak *= i;
}
}
return fak;
}
You seem to have worked with another language before. Java works a bit different than you seem to expect.
for (int i = 0; i <= k; k++) {
fak *= (2 * i + 1);
}
This particular loop is definetly not working as expected. You increment k, but iis supposed to grow? Might be you want to write:
for (int i = 0; i <= k; i++) {
fak *= (2 * i + 1);
}
Because the loop counts k, instead of i, it continues, until k overruns the integer-range and becomes Integer.MIN_VALUE. At that point, your loop finally terminates. :)
On a completely different note, and meant as constructive critique: You might want to take a look at the default Java-Style-Guide (https://github.com/twitter/commons/blob/master/src/java/com/twitter/common/styleguide.md)
Small excerpt:
// Bad.
// - This offers poor visual separation of operations.
int foo=a+b+1;
// Good.
int foo = a + b + 1;
Spaces between identifiers and operators are very, very helpful, operating with numbers, but also with a lot of different stuff.
It is not quite clear to me what you are calculating in berechnePot and berechnePot. They seem to be the numerators and denominators, judging from the context.
Running your code with a debugger, I can see that summand is calculated very wrongly, and decreases very slowly. This is the reason why it takes so long.
The Math class provides a pow method, so you don't really need to use a for loop to calculate powers. I think you might be overcomplicating this a bit. I would write a getSummand method and a factorial method:
private static double getSummand(double x, int k) {
int power = k * 2 + 1;
double numerator = Math.pow(x, power);
double denominator = factorial(power);
int sign = k % 2 == 1 ? -1 : 1;
return numerator / denominator * sign;
}
private static double factorial(int x) {
double result = 1;
for (int i = 1; i <= x; i++) {
result *= i;
}
return result;
}
And use them like this:
public static double sinus(double x) {
double error = 0.001;
double summand = 0;
double sum = 0;
int k = 0;
do {
summand = getSummand(x, k);
sum += summand;
k++;
} while (Math.abs(summand) > error);
return sum;
}
If this is an assignment and you are not allowed to use anything from the Math class, you could write your own pow method like this:
private static double pow(double x, int p) {
double result = 1;
for (int i = 0 ; i < p ; i++) {
result *= x;
}
return result;
}
In your berechneFak() function you have a loop inside the else clause. You do increment k but not i so i <= k is always true. Try looking at it in a debugger. This is the loop that is slowing it down.
So every time k will count up to the max integer value of 2,147,483,647 in single increments and then overflow to a negative value at which point the loop will end.
Just to clarify: I did not look at if the math is correct but just at why the program is slow.
Related
I'm trying to write the Power method and now the question is how to write it in a better way. Here is my code, I've verified it works well for all the Power conditions, however I can't think on a better solution.
The real issue is how I express the power with a Negative exponent in O(log)n condition
public static double raiseToPowerIterative(double x, int n) {
double sol = 1;
if (n == 0) {
return 1;
}
if (n > 0) {
for (int i = 1; i <= n;i++) {
sol *= x;
}
return sol;
} else if (n < 0){
for (int i = -1; i >= n; i--) {
sol /= x;
}
}
return sol;
}
You need some additional math rules, you are using:
xn = x.x. ... .x (n times)
With O(n)
However
x2k = xk . xk
x2k+1 = x.x2k
Which can deliver O(²log n), as you are doing exponents n → n/2 → n/2/2 → ... → 1.
Where you only need to calculate xk once.
A recursive solution might be easiest; calling oneself for xk.
Your solution:
That does not work, I think. As probably past limit date of the work.
Wrong:
double power(double x, int n) {
if (n == 0) {
return 1;
}
boolean negative = ( n < 0 );
if (negative) {
n = -n;
}
double sol = 1;
while (n > 0) {
if (n%2 == 1) {
sol *= x;
}
x *= x;
n /= 2;
}
if (negative) {
return 1 / sol;
}
return sol;
}
Correct recursive:
double power(double x, int n) {
if (n == 0) {
return 1;
} else if (n < 0) {
return 1 / power(x, -n);
}
double sqrPower = power(x, n/2);
int p = sqrPower * sqrPower;
if (n % 1 == 1) {
p *= x;
}
return p;
}
That is, one has to do something with the result of the recursive call.
For an iterative loop one would need a stack to reconstruct the result.
Correct iterative:
double power(double x, int n) {
if (n == 0) {
return 1;
}
boolean invert = n < 0;
if (invert) {
n = -n;
}
Stack<Double> factors = new Stack<>();
while (n > 0) {
factors.push(n % 1 == 1 ? x : 1.0);
n /= 2;
}
double sol = 1;
while (!factors.empty()) {
double f = factors.pop();
sol = sol * sol * f;
}
return invert ? 1/sol : sol;
}
In "Think Java" by Allen B. Downey, I am stuck on question 7.6. The question asks to evaluate e^{(-x)^2} without using factorial or exponent functions. I got the code working for x = 2, but not other numbers.
public static double gauss2(double x, double n) {
double i = 2;
double count = n;
double num = 1;
while (i <= n){
num = ((x*x)/(i - 1))*num;
i = i + 1;
}
if (n == 1) {
return 1;
}
else if (n%2 == 0) {
return num*(-1) + gauss2(x,n-1);
}
else {
return num + gauss2(x, n-1);
}
The Maclaurin series for ex is useful. It goes:
ex = Σ{n = 0 to ∞} (xn/n!)
So, some simple code to get approximate results is:
public final class Exponential {
private static final int ITERATIONS = 32;
public static final double exp(final double x) {
double power = 1.0;
double factorial = 1.0;
double result = 1.0;
for (int n = 1; n <= ITERATIONS; n++) {
power *= x;
factorial *= n;
result += power/factorial;
}
return result;
}
public static final void main(String[] args) {
System.out.println("Testing Math.exp against Exponential.exp for a few inputs");
for (double exponent = -5.0; exponent <= 5.0; exponent += 0.1) {
System.out.printf("e^%f = %f = %f\n", exponent, Math.exp(exponent), exp(exponent));
}
}
}
You can then use exp((-x)*(-x)).
i need to take 2 inputted numbers and calculate variable 1 to the power of variable 2 is without using math.pow and using a for loop. This is what i have now
Scanner in = new Scanner(System.in);
System.out.print("Please enter your base: ");
int base = in.nextInt();
System.out.print("Please enter your exponent: ");
int power = in.nextInt();
int result = mathPower(base, power);
System.out.println(base + " to the power of " + power + " is " + result + ".");
}
public static int mathPower(int a, int b)
{
int result = a;
if (b == 0) {
result = 1;
}
if (b < 0) {
a = (1 / a);
b = -b;
}
for (a = 1; a < b; a++) {
result = result * a;
return result;
}
return result;
}
}
It only seems to work if the exponent is 0, otherwise it just displays the a value. I need both positive and negative exponents. Thanks in advance!
The case with b<0 only makes sense with floating point numbers, so I changed the type of a and the return value to double.
public static double mathPower(double a, int b)
{
double result = 1;
if (b < 0) {
a = 1.0 / a;
b = -b;
}
for (int i = 0; i < b; i++) {
result = result * a;
}
return result;
}
You have three main problems:
The return statement inside the loop is breaking it in the first repetition.
You're using your a variable as the loop variable.
If you allow negative exponents then the return value should be a double.
public static double mathPower(double a, int b)
{
double result = 1.0;
if (b == 0)
{
result = 1.0;
}
if (b < 0)
{
a = (1.0 / a);
b = -b;
}
for (int i = 0; i < b; i++)
{
result = result * a;
}
return result;
}
suppose you have numb1=2 and numb2=6.
then
temp=1;
if (numb2 < 0) {
numb1 = 1 / numb1;
numb2 = -numb2;
}
for(int n = 1; n<=numb2; n++){
temp=temp*numb1;
}
public double power(double base,int pow)
{
double result = 1;
if(pow==0)
return 1;
if(base == 0)
return 0;
if(pow>0)
{
for(int i = 0;i<pow;i++)
{
result *= base;
}
}
else
{
for(int i = pow;i<0;i++)
{
result *= base;
}
result = 1/result;
}
return result;
}
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;
}
I'm basically trying to rewrite math.pow, I have the following obviously I'm not getting the concept of returning values. What exactly am I doing wrong?
public static int power(int x, int n)
{
if (n == 0) return 1;
int i,total;
for(i = 0; i < n-1 ;i++);
{
total = (x * total);
}
return total;
}
You need to initialize total to 1.
int total = 1;
You can just rewrite everything to:
public static int power(int x, int n)
{
int total = 1;
for(int i = 0; i < n; i++) // i can be declared here directly
{
total = (x * total);
}
return total; // total remains 1 if n = 0
}
public static int power(int x, int n)
{
int total = 1; // Initialized total to 1
for(int i = 0; i < n; i++)
{
total = x*total;
}
return total;
}
instead of i < n-1 you should use i <= n-1 or i < n and int total=1. hope it will work.
also remove ; from the for loop end. rewriting the code
public static int power(int x, int n){
int total=1;
for(int i = 0;i < n;i++)
total *= x;
return total;
}
For one, it looks like you meant:
if (n == 0) return 1;
check the power, not the base number.
You're not initialisign total either, using total = x would fix things i think.
The variable total starts at 0. So calling total = x*total will always be 0.
You need to initialize total to x.
Here is a solution with log(n) complexity instead of linear. Be careful with overflow though.
int pow(int x, int n) {
int res = 1;
while(n > 0) {
if(n % 2 == 1) {
res = res * x;
}
x = x * x;
n = n / 2;
}
return res;
}