How to write a cosine theorem using Java? - java

How to write this theorem correctly as is written in the formula?
package com.company;
public class Exercise8 {
public static void main(String[] args) {
double AB = 6;
double AC = 16;
double Angle = 60;
double CosOfAngle = 0.5;
// Почему-то значение косинуса 60 градусов вместо 0.5, пишет
// -0.9524129804151563 ? ? ? (Do not pay attention)
// Formula is BC^2 = AB^2 + AC^2 - 2AB*AC * cos A
double bc = (2 * (Math.pow(AB, 2) + Math.pow(AC, 2) - ((AB * AC))) * CosOfAngle);
double BC = Math.sqrt(bc);
double P = AB + BC + AC;
double p = 0.5 * P; // Где p - полупериметр
double S0 = (p * ((p - AB) * (p - BC) * (p - AC)));
double S1 = Math.sqrt(S0);
double S = Math.round(S1);
System.out.println("Perimeter of triangle is : " + P + " cm ");
System.out.println("Area of triangle is : " + S + " cm^2 ");
}
}

The mistake is in this line:
double bc = (2 * (Math.pow(AB, 2) + Math.pow(AC, 2) - ((AB * AC))) * CosOfAngle);
which should be:
double bc = Math.pow(AB, 2) + Math.pow(AC, 2) - 2 * AB * AC * CosOfAngle;
You were multiplying the whole formula by 2, whereas only the cosine part needs to be multiplied by two. There were too many confusing parenthesis. Removing them made it a lot clearer.

This seems simple to me:
// https://www.mathsisfun.com/algebra/trig-cosine-law.html
public double lawOfCosines(double a, double b, double angleInRadians) {
return Math.sqrt(a*a + b*b - 2.0*a*b*Math.cos(angleInRadians));
}

Related

Placement of Math.toRadians for solving quadratic and cubic equations

I am writing a program which solves either quadratic or cubic equations. The thing is that I don't know if I am placing the Math.toRadians correctly.
The code is the following:
public double[] getRaices(double a,double b, double c, double d) throws ComplexException {
if (a==0){
double discriminante=Math.pow(c,2)+((-4)*b*d);
if(discriminante>=0){
this.Raices[0]=(c*(-1)+Math.sqrt(discriminante))/(2*b);
this.Raices[1]=(c*(-1)-Math.sqrt(discriminante))/(2*b);
}else{
throw new ComplexException("No hay solucion Real");
}
} else{
double f=((3*c/a)-(Math.pow(b,2)/Math.pow(a,2)))/3;
double g=((2*Math.pow(b,3)/Math.pow(a,3))-(9*b*c/Math.pow(a,2))+(27*d/a))/27;
double h=(Math.pow(g,2)/4)+(Math.pow(f,3)/27);
if(f+g+h==0){
Raices [0]=Math.cbrt(d/a)*(-1);
Raices [1]=Math.cbrt(d/a)*(-1);
Raices [2]=Math.cbrt(d/a)*(-1);
}else{
if(h<=0){
double i=Math.sqrt((Math.pow(g,2)/4)-h);
double j=Math.cbrt(i);
double k=Math.acos(Math.toRadians(-1*(g/2*i)));
System.out.println(" "+k+" ");
double l=j*(0-1);
double m=Math.toRadians(Math.cos(Math.toRadians(k/3)));
System.out.println(" "+m+" ");
double n=Math.sqrt(3)*Math.sin(Math.toRadians(k/3));
System.out.println(" "+n+" ");
double p=(b/(3*a)*(0-1));
Raices [0]=2*j*Math.cos(Math.toRadians(k/3))-(b/(3*a));
Raices [1]=(l*(m+n))+p;
Raices [2]=(l*(m-n))+p;
}else{
double r=((0-1)*(g/2))+Math.sqrt(h);
double s=Math.cbrt(r);
double t=((0-1)*(g/2))-Math.sqrt(h);
double u=Math.cbrt(t);
throw new ComplexException("2 de las raices son imaginarias pero una raiz es real: "+Math.floor(Raices [0]=(s+u)-(b/(3*a))));
}
}
}
return Raices;
}
But the problem is in the if (h<=0).
I tested your code against the web page and found several errors.
First is g /2i, you wrote g/2*i instead of g/2/i or (g/(2*i). And several Math.toRadians not necessary (webpage said calculations is in radians, so no need to convert).
I added println to help following the formula :
package test;
public class Cubic {
private double[] Raices = new double[3];
public static void main(String[] args) throws ComplexException {
double[] raices = new Cubic().getRaices(2, -4, -22, 24);
System.out.println(raices[0] + "," + raices[1] + "," + raices[2]);
}
public double[] getRaices(double a, double b, double c, double d) throws ComplexException {
if (a == 0) {
double discriminante = Math.pow(c, 2) + ((-4) * b * d);
if (discriminante >= 0) {
this.Raices[0] = (c * (-1) + Math.sqrt(discriminante)) / (2 * b);
this.Raices[1] = (c * (-1) - Math.sqrt(discriminante)) / (2 * b);
} else {
throw new ComplexException("No hay solucion Real");
}
} else {
double f = ((3 * c / a) - (Math.pow(b, 2) / Math.pow(a, 2))) / 3;
System.out.println("f=" + f);
double g = ((2 * Math.pow(b, 3) / Math.pow(a, 3)) - (9 * b * c / Math.pow(a, 2)) + (27 * d / a)) / 27;
System.out.println("g=" + g);
double h = (Math.pow(g, 2) / 4) + (Math.pow(f, 3) / 27);
System.out.println("h=" + h);
if (f + g + h == 0) {
Raices[0] = Math.cbrt(d / a) * (-1);
Raices[1] = Math.cbrt(d / a) * (-1);
Raices[2] = Math.cbrt(d / a) * (-1);
} else {
if (h <= 0) {
double i = Math.sqrt((Math.pow(g, 2) / 4) - h);
double j = Math.cbrt(i);
double k = Math.acos(-1 * (g / 2 / i));
System.out.println("k=" + k + " ");
double l = j * (0 - 1);
System.out.println("l=" + l + " ");
double m = Math.cos(k / 3);
System.out.println("m= " + m + " ");
double n = Math.sqrt(3) * Math.sin(k / 3);
System.out.println("n= " + n + " ");
double p = (b / (3 * a) * (0 - 1));
System.out.println("p= " + p + " ");
Raices[0] = 2 * j * Math.cos(k / 3) - (b / (3 * a));
Raices[1] = (l * (m + n)) + p;
Raices[2] = (l * (m - n)) + p;
} else {
double r = ((0 - 1) * (g / 2)) + Math.sqrt(h);
double s = Math.cbrt(r);
double t = ((0 - 1) * (g / 2)) - Math.sqrt(h);
double u = Math.cbrt(t);
throw new ComplexException(
"2 de las raices son imaginarias pero una raiz es real: " + Math.floor(Raices[0] = (s + u) - (b / (3 * a))));
}
}
}
return Raices;
}
}

How to solve this set of nonlinear trigonometric equations in Java?

I am trying to solve a system of trigonometric equations in Java, but I don't know where to start. I've used commons-math3 before to solve simple linear sets of equations, but this is above my head. Equations I am trying to solve:
a - e + bcosθ1 + csinθ1 + d*sin(θ2+θ1)= z
( bsinθ1 + ccosθ1 + d*cos(θ2-θ1) * sinθ0 = x
( bsinθ1 + ccosθ1 + d*cos(θ2-θ1) * sinθ0 = y
, where a,b,c,d and e are constants. In practical terms, given x, y, and z, I need to solve for θ0, θ1, θ2.
You need to use the root-finding algorithm.
It is usually studied in calculus as the Newton's method or Newton Raphson method.
You will have to use a multi-dimensional secant method or Muller's method. Numerical recipes has something on it.
You can use the least-squares-in-java project for this. Here’s the code that will solve your problem:
import org.junit.Assert;
import org.junit.Test;
import org.orangepalantir.leastsquares.Function;
public class NonLinearTrigonometricSolver {
// Solves the following non-linear set of equations:
// a - e + bcosθ1 + csinθ1 + d * sin(θ1 + θ2) ) = z
// ( bsinθ1 + ccosθ1 + d * cos(θ1 + θ2) ) * sinθ0 = x
// ( bsinθ1 + ccosθ1 + d * cos(θ1 + θ2) ) * cosθ0 = y
// given x, y, z, solve for θ0, θ1, θ2
static final double a = 125;
static final double b = 143;
static final double c = 50;
static final double d = 142;
static final double e = 96;
static final double x = 0;
static final double y = 192;
static final double z = 172;
#Test
public void testNonLinearTrigonometricSolver() {
double[][] xs = { { -1 }, { 0 }, { 1 } };
double[] zs = { z, x, y };
double r = Math.sqrt(x * x + y * y);
final double sinTheta0 = x / r;
final double cosTheta0 = y / r;
Function f = new Function() {
#Override
public double evaluate(double[] values, double[] parameters) {
double t1 = parameters[0];
double t2 = parameters[1];
if (values[0] == -1) {
return a - e + b * Math.sin(t1) + c * Math.cos(t1) + d * Math.cos(t2 + t1);
} else if (values[0] == 0) {
return (b * Math.sin(t1) + c * Math.cos(t1) + d * Math.cos(t2 + t1)) * sinTheta0;
} else {
return (b * Math.sin(t1) + c * Math.cos(t1) + d * Math.cos(t2 + t1)) * cosTheta0;
}
}
#Override
public int getNParameters() {
return 2;
}
#Override
public int getNInputs() {
return 1;
}
};
NonLinearSolver fit = new NonLinearSolver(f);
fit.setData(xs, zs);
double[] params = { 0, 0 };
fit.setParameters(params);
fit.fitData();
// improving results.
fit.setMinChange(1e-32);
fit.setMinError(1e-32);
fit.setStepSize(0.5);
fit.fitData();
double t1 = fit.getParameters()[0];
double t2 = fit.getParameters()[1];
double arg = y / (b * Math.sin(t1) + c * Math.cos(t1) + d * Math.cos(t2 + t1));
// System.out.println(" " + arg);
double theta0 = Math.acos(arg) * Math.signum(x);
System.out.println(Math.toDegrees(theta0));
System.out.println(Math.toDegrees(fit.getParameters()[0]));
System.out.println(Math.toDegrees(fit.getParameters()[1]));
Assert.assertEquals(0, Math.toDegrees(theta0), 1e-16);
Assert.assertEquals(0, Math.toDegrees(fit.getParameters()[0]), 1e-16);
Assert.assertEquals(0, Math.toDegrees(fit.getParameters()[1]), 1e-16);
}
}

basic math equation math to java code

so i have a math equation that i need to use in java but for some reason my code is giving me small errors :(
the math equation is describe on this web page in the section extra credit
my current code outpouts 4000 and the answere is 4005 what am i duing wrong ?
my test class lookes like this
public class MainActivity {
public static void main(String[] args) throws Exception{
double baseMaterial =556;
int me =5;
int ml = 10;
int extraMaterial = 3444;
System.out.println(""+calculateMiniralTotal(baseMaterial,me,ml,extraMaterial));
}
public static double calculateMiniralTotal(double perfekt,int me,int ml,int extraMaterial) {
double s = (perfekt + (perfekt * (10 / (ml + 1)) / 100));
s = Math.round(s);
double r = s + (perfekt * (0.25 - (0.05 * me)));
r = Math.round(r);
double q = extraMaterial + (extraMaterial * (0.25 - (0.05 * me)));
q = Math.round(q);
//double r=q;
r = r + q;
return Math.round(r);
}
}
You are performing integer division with (10 / (ml + 1)) / 100, which in Java must result in another int. Your ml is 10, and in Java, 10 / 11 is 0, not 0.909..., and nothing is added to s.
Use a double literal or cast to double to force floating-point computations.
double s = (perfekt + (perfekt * (10.0 / (ml + 1)) / 100));
or
double s = (perfekt + (perfekt * ( (double) 10 / (ml + 1)) / 100));
Making either change makes the output:
4005.0
When you multiply a double by an int you get an int back.
public class Main
{
public static void main(String[] args)
throws Exception
{
double baseMaterial = 556;
int me = 5;
int ml = 10;
int extraMaterial = 3444;
System.out.println("" + calculateMiniralTotal(baseMaterial, me, ml, extraMaterial));
}
public static double calculateMiniralTotal(double perfekt, int me, int ml, int extraMaterial)
{
double s = (perfekt + (perfekt * (10.0 / (ml + 1)) / 100.0)); // <-- changed from 10 to 10.0 and 100 to 100.0. This way they are doubles too
s = Math.round(s);
double r = s + (perfekt * (0.25 - (0.05 * me)));
r = Math.round(r);
double q = extraMaterial + (extraMaterial * (0.25 - (0.05 * me)));
q = Math.round(q);
// double r=q;
r = r + q;
return Math.round(r);
}
}

Perlin noise value range

I used perlin noise to generate a 2D height map. At first i tried some parameters manually and found a good combination of amplitude, persistence,... for my job.
Now that i'm developing the program, i added the feature for user to change the map parameters and make a new map for himself but now i see that for certain parameters (Mostly octaves and frequency) the values are not in the range i used to see. I thought that if a set Amplitude = 20, the values(heights) i get from it will be in e.g [0,20] or [-10,10] or [-20,20] ranges but now i see that Amplitude is not the only parameter that controls output range.
My question is: Is there an exact mathematical formula (a function of Amplitude, Octaves, Frequency and persistence) to compute the range or i should take a lot of samples (like 100,000) and check minimum and maximum values of them to guess the aproximate range?
Note: The following code is an implementation of perlin noise that one of stackoverflow guys worte it in C and i ported it to java.
PerlinNoiseParameters.java
public class PerlinNoiseParameters {
public double persistence;
public double frequency;
public double amplitude;
public int octaves;
public int randomseed;
public PerlinNoiseParameters(double persistence, double frequency, double amplitude, int octaves, int randomseed) {
this.ChangeParameters(persistence, frequency, amplitude, octaves, randomseed);
}
public void ChangeParameters(double persistence, double frequency, double amplitude, int octaves, int randomseed) {
this.persistence = persistence;
this.frequency = frequency;
this.amplitude = amplitude;
this.octaves = octaves;
this.randomseed = 2 + randomseed * randomseed;
}
}
PerlinNoiseGenerator.java
public class PerlinNoiseGenerator {
PerlinNoiseParameters parameters;
public PerlinNoiseGenerator() {
}
public PerlinNoiseGenerator(PerlinNoiseParameters parameters) {
this.parameters = parameters;
}
public void ChangeParameters(double persistence, double frequency, double amplitude, int octaves, int randomseed) {
parameters.ChangeParameters(persistence, frequency, amplitude, octaves, randomseed);
}
public void ChangeParameters(PerlinNoiseParameters newParams) {
parameters = newParams;
}
public double get(double x, double y) {
return parameters.amplitude * Total(x, y);
}
private double Total(double i, double j) {
double t = 0.0f;
double _amplitude = 1;
double freq = parameters.frequency;
for (int k = 0; k < parameters.octaves; k++) {
t += GetValue(j * freq + parameters.randomseed, i * freq + parameters.randomseed)
* _amplitude;
_amplitude *= parameters.persistence;
freq *= 2;
}
return t;
}
private double GetValue(double x, double y) {
int Xint = (int) x;
int Yint = (int) y;
double Xfrac = x - Xint;
double Yfrac = y - Yint;
double n01 = Noise(Xint - 1, Yint - 1);
double n02 = Noise(Xint + 1, Yint - 1);
double n03 = Noise(Xint - 1, Yint + 1);
double n04 = Noise(Xint + 1, Yint + 1);
double n05 = Noise(Xint - 1, Yint);
double n06 = Noise(Xint + 1, Yint);
double n07 = Noise(Xint, Yint - 1);
double n08 = Noise(Xint, Yint + 1);
double n09 = Noise(Xint, Yint);
double n12 = Noise(Xint + 2, Yint - 1);
double n14 = Noise(Xint + 2, Yint + 1);
double n16 = Noise(Xint + 2, Yint);
double n23 = Noise(Xint - 1, Yint + 2);
double n24 = Noise(Xint + 1, Yint + 2);
double n28 = Noise(Xint, Yint + 2);
double n34 = Noise(Xint + 2, Yint + 2);
double x0y0 = 0.0625 * (n01 + n02 + n03 + n04) + 0.1250
* (n05 + n06 + n07 + n08) + 0.2500 * n09;
double x1y0 = 0.0625 * (n07 + n12 + n08 + n14) + 0.1250
* (n09 + n16 + n02 + n04) + 0.2500 * n06;
double x0y1 = 0.0625 * (n05 + n06 + n23 + n24) + 0.1250
* (n03 + n04 + n09 + n28) + 0.2500 * n08;
double x1y1 = 0.0625 * (n09 + n16 + n28 + n34) + 0.1250
* (n08 + n14 + n06 + n24) + 0.2500 * n04;
double v1 = Interpolate(x0y0, x1y0, Xfrac);
double v2 = Interpolate(x0y1, x1y1, Xfrac);
double fin = Interpolate(v1, v2, Yfrac);
return fin;
}
private double Interpolate(double x, double y, double a) {
double negA = 1.0 - a;
double negASqr = negA * negA;
double fac1 = 3.0 * (negASqr) - 2.0 * (negASqr * negA);
double aSqr = a * a;
double fac2 = 3.0 * aSqr - 2.0 * (aSqr * a);
return x * fac1 + y * fac2;
}
private double Noise(int x, int y) {
int n = x + y * 57;
n = (n << 13) ^ n;
int t = (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff;
return 1.0 - (double) t * 0.931322574615478515625e-9;
}
}
The range of a single perlin noise step is:
http://digitalfreepen.com/2017/06/20/range-perlin-noise.html
-sqrt(N/4), sqrt(N/4)
With N being the amount of dimensions. 2 in your case.
Octaves, persistence and amplitude add on top of that:
double range = 0.0;
double _amplitude = parameters.;
for (int k = 0; k < parameters.octaves; k++) {
range += sqrt(N/4) * _amplitude;
_amplitude *= parameters.persistence;
}
return range;
There might be some way to do this as a single mathematical expression. Involving pow(), but by brain fails me right now.
This is not a problem with octaves and frequency affecting amplitude, not directly at least. It is a problem with integer overflow. Because you introduce your random seed by adding it to the the x and y co-ordinates (which is unusual, I don't think this is the usual implimentation)
t += GetValue(j * freq + parameters.randomseed, i * freq + parameters.randomseed)* _amplitude;
And random seed could be huge (possibly the near full size of the int) because
this.randomseed = 2 + randomseed * randomseed;
So if you input large values for j and i you end up with the doubles that are passed through at GetValue(double x, double y) being larger than the maximum size of int, at that point when you call
int Xint = (int) x;
int Yint = (int) y;
Xint and YInt won't be anything like x and y (because x and y could be huge!) and so
double Xfrac = x - Xint;
double Yfrac = y - Yint;
could be much much larger that 1, allowing values not between -1 and 1 to be returned.
Using reasonable and small values my ranges using your code are between -1 and 1 (for amplitude 1)
As an asside, in java usually method names are methodName, not MethodName
If its useful please find annother java implimentation of perlin noise here:
http://mrl.nyu.edu/~perlin/noise/

coneVolume Method returning zero

I can't seem to figure out why my coneVolume method is returning zero when all of my other methods are working properly.
import java.util.Scanner;
public class P56old{
public static double sphereVolume(double r){
double sphereVolume = (4/3)*(Math.PI)*(Math.pow(r, 3));
return sphereVolume;
}
public static double sphereSurface(double r){
double sphereSurface = 4 * (Math.PI) * Math.pow(r, 2);
return sphereSurface;
}
public static double cylinderVolume(double r, double h){
double cylinderVolume = (Math.PI) * (Math.pow(r, 2)) * h;
return cylinderVolume;
}
public static double cylinderSurface(double r, double h){
double cylinderSurface = 2 * (Math.PI) * (Math.pow(r, 2)) + 2 * Math.PI * r * h;
return cylinderSurface;
}
public static double coneVolume(double r, double h){
double coneVolume = (1/3) * Math.PI * (Math.pow(r,2)) * h;
return coneVolume;
}
public static double coneSurface(double r, double h){
double s = Math.sqrt(Math.pow(r,2) + Math.pow(h, 2));
double coneSurface = Math.PI * Math.pow(r,2) + Math.PI * r * s;
return coneSurface;
}
public static void main(String[] args){
Scanner in = new Scanner(System.in);
System.out.print("Please give the radius: ");
double r = in.nextDouble();
System.out.print("Please give the height: ");
double h = in.nextDouble();
double coneVolume = coneVolume(r,h);
double sphereVolume = sphereVolume(r);
double sphereSurface = sphereSurface(r);
double cylinderVolume = cylinderVolume(r,h);
double cylinderSurface = cylinderSurface(r,h);
double coneSurface = coneSurface(r,h);
System.out.println("The Sphere Volume is " + sphereVolume);
System.out.println("The Sphere Surface is " + sphereSurface);
System.out.println("The Cylinder volume is " + cylinderVolume);
System.out.println("The Cylinder Surface is " + cylinderSurface);
System.out.println("The Cone Volume is " + coneVolume);
System.out.println("The Cone Surface is " + coneSurface);
}
}
I'd appreciate any insight on the matter, and any critique is appreciated. I think it may have to do with all the public classes and maybe another method is affecting the coneVolume method but I just don't know enough about methods at the moment to fix the issue at hand.
When you do 1/3, it does integer division, resulting in 0 (the remainder is 1). Multiplying by 0 gives 0. Do 1.0/3.0 instead, and it will correctly compute an approximation to one third.

Categories

Resources