I need to convert the following python code to Java and remember from the past that handling decimal values must be done carefully otherwise the results will not be accurate.
My question is, can I use doubles for all non-interger values given doubles are more accurate that floats?
Here is my start of the conversion:
Python code
def degrees(rads):
return (rads/pi)*180
def radians(degrees):
return (degrees/180 * pi)
def fnday(y, m, d, h):
a = 367 * y - 7 * (y + (m + 9) // 12) // 4 + 275 * m // 9
a += d - 730530 + h / 24
return a
Java conversion
public double degress(double rads)
{
return (rads/PI)*180;
}
public double radians(double degrees)
{
return (degrees/180 * PI);
}
public double fnday(int y, int m, int d, int h)
{
double a = 367 * y - 7 * (y + (m + 9) / 12) / 4 + 275 * m / 9;
a += d - 730530 + h / 24;
return a;
}
I know it may be a simple answer but I need to know the postion of the moon and sun for the app and do not want to rely on an api for this data. I simple want to put in the latitude and longitdue and get the sun and moon rise and set times.
Using a double for each variable would suffice; however, you have an issue that results from integer division:
double a = 367 * y - 7 * (y + (m + 9) / 12) / 4 + 275 * m / 9;
If I were you, I'd change y, m, d, and h to all be doubles, so you retain the decimal places when dividing:
public double fnday(double y, double m, double d, double h) {
double a = 367 * y - 7 * (y + (m + 9) / 12) / 4 + 275 * m / 9;
a += d - 730530 + h / 24;
return a;
}
If you need a really big precision, the best way is use,
java.lang.BigDecimal, that extends from java.math.Number.
You can even use your existing doubles if you need:
double d = 67.67;
BigDecimal bd = new BigDecimal(d);
But you will need to use the methods from the class like this:
public BigDecimal degress(BigDecimal rads)
{
BigDecimal pi = new BigDecimal(PI);
return (rads.divide(pi))*180;
}
Related
This converter assumes H, S, and L are contained in the set [0, 1].
But I want H to be between [0, 359] (0 and 359 included) and S & L between [0, 100] (0 and 100 included) and I don't know how to do it (in Java as well).
I took this converter from here.
public class testdos {
public static void main(String[] args) {
// hslToRgb([0, 359], [0, 100], [0, 100]);
}
public static int[] hslToRgb(float h, float s, float l) {
// i added this sysout line
System.out.println("HSL(" + h + "," + s + "," + l + ")");
float r, g, b;
if (s == 0f) {
r = g = b = l; // achromatic
} else {
float q = l < 0.5f ? l * (1 + s) : l + s - l * s;
float p = 2 * l - q;
r = hueToRgb(p, q, h + 1f / 3f);
g = hueToRgb(p, q, h);
b = hueToRgb(p, q, h - 1f / 3f);
}
int[] rgb = { to255(r), to255(g), to255(b) };
// and i added this to print it, don't know if its the best way to do it
System.out.print("RGB(");
for (int i = 0; i < rgb.length; i++) {
if ((i + 1) != rgb.length) {
System.out.print(rgb[i] + ",");
}
else {
System.out.print(rgb[i]);
}
}
System.out.println(")");
return rgb;
}
public static int to255(float v) {
return (int) Math.min(255, 256 * v);
}
/** Helper method that converts hue to rgb */
public static float hueToRgb(float p, float q, float t) {
if (t < 0f)
t += 1f;
if (t > 1f)
t -= 1f;
if (t < 1f / 6f)
return p + (q - p) * 6f * t;
if (t < 1f / 2f)
return q;
if (t < 2f / 3f)
return p + (q - p) * (2f / 3f - t) * 6f;
return p;
}
}
The hslToRgb() method you provided accepts three parameters of float data type. The value range that must be provided to all of these parameters is: 0.0f to 1.0f:
int[] hslToRgb(float h, float s, float l) { ... }
Instead you want to supply a specific range values to these parameters which in turn makes the method much easier to utilize in layman's terms with respect to what needs to actually be supplied.
H (0° to 360° as in Degrees)
S (0% to 100% as in Percent)
L (0% to 100% as in Percent)
It's all a matter of doing a little division. This can be done as the parameters are supplied to the method or built into the method which appears to be what you want. The latter is somewhat more advantageous since you don't need to remember the formula (regardless of how simple it is) to carry out those divisions when applying the arguments to the hslToRgb() method.
Doing the math before passing arguments:
// Hue is: 65° Saturation is: 36% Lightness is: 87%
float hue = (float) 65/360;
float saturation = (float) 36/100;
float lightness = (float) 87/100;
int[] rgb = hslToRgb(hue, saturation, lightness);
Doing the math when passing arguments:
// Hue is: 65° Saturation is: 36% Lightness is: 87%
int[] rgb = hslToRgb((float)65/360, (float)36/100, (float)87/100);
Who cares! Let the method figure it out:
// Hue is: 65° Saturation is: 36% Lightness is: 87%
int[] rgb = hslToRgb(65, 36, 87);
This last example requires a little bit of code to be added to the hslToRgb() method. It's nothing major but before we get into that you need to be sure to realize that for color accuracy, Hue, Saturation, and Lightness arguments can be given respectively in floating point degree and floating point percentage values. In other words, supplying arguments such as:
int[] rgb = hslToRgb(65, 36, 87);
AND
int[] rgb = hslToRgb(65.8, 36.2, 87.5);
are to be considered valid calls with valid arguments. With the slight code addition to the hslToRgb() method, either or can be supplied, for example:
int[] rgb = hslToRgb(0.1806f, 36, 87.5);
This is a valid call with valid arguments and will produce the very same RGB values as the other above examples.
Modifying the hslToRgb() method:
Simply add these three lines of code to the top of the hslToRGB() method:
public static int[] hslToRGB(float h, float s, float l) {
if (h > 1.0f) { h = (h < 0 ? 0 : h > 360 ? 360 : h) / 360; }
if (s > 1.0f) { s = (s < 0 ? 0 : s > 100 ? 100 : s) / 100; }
if (l > 1.0f) { l = (l < 0 ? 0 : l > 100 ? 100 : l) / 100; }
// .... the rest of method code here ....
}
What are these three lines of code doing?
With these lines of code the Hue (h) argument can be supplied as a set [0.0 to 1.0] or a set [0.0 to 360.0] or a set [0 to 360]. The Saturation (s) and Lightness (l) arguments can be supplied as a set [0.0 to 1.0] or a set [0.0 to 100.0] or a set [0 to 100]. If any argument supplied is less than its minimum range (0) then it is defaulted to that arguments specific minimum which for all arguments would be 0. On the same hand, if any argument supplied is greater than its maximum range then it is defaulted to that arguments specific maximum.
Since all three lines of code are basically doing the same thing for each specific argument, we'll explain the first line:
if (h > 1.0f) { h = (h < 0 ? 0 : h > 360 ? 360 : h) / 360; }
The condition for the if statement (h > 1.0f) checks to see if the supplied Hue (h) argument is within the set of [0.0 to 1.0]. If the argument supplied is greater than 1.0 then it must be supplied as a literal degree value and the if statement condition is true therefore running the code contained within this statement's code block which consists of nested Ternary Operator statements. If the if statement condition is false then the supplied value is merely used. Ultimately, if the condition is true then we want to take the supplied argument and divide it by 360 but first we use the nested Ternary Operator statements to ensure the argument supplied is within valid range (0 to 360):
h < 0 ? 0 :
If the supplied argument (h) is less than 0 (such as an arbitrary value of -22 or -0.202) then the h is set to hold a default of 0 otherwise we check to see if the argument value is greater then 360:
: h > 360 ? 360 :
If the supplied argument (h) is greater than 360 (such as an arbitrary value of 365 or 378.8) then the h is set to hold a default of 360 otherwise it is deemed that the argument supplied is indeed within the proper range and we'll use it therefore dividing the supplied value by 360;
: h) / 360
How you might use this method:
int[] rgb = hslToRGB(65, 36, 87);
System.out.println("RGB is: " + java.util.Arrays.toString(rgb));
String hex = "#" + Integer.toHexString(new Color(rgb[0], rgb[1], rgb[2]).getRGB() & 0x00ffffff);
System.out.println("In Hexadecimal: " + hex.toUpperCase());
Console Output:
RGB is: [232, 234, 210]
In Hexadecimal: #E8EAD2
You divide by the h, s, and l range to get the numbers between 0 and 1. You also start class names with an upper-case character.
Edited to add: Why do I have to start class names with an upper-case character?
Because it's the Java convention, and so you can write code like:
Testdoc testdoc = new TestDoc();
and visually see the difference between the Testdoc class name and the testdoc field name.
Here's the revised code.
public class Testdos {
public static void main(String[] args) {
// hslToRgb([0, 359], [0, 100], [0, 100]);
}
/**
* Converts an HSL color value to RGB. Conversion formula adapted from
* http://en.wikipedia.org/wiki/HSL_color_space. Assumes h, s, and l are
* contained in the set [0, 1] and returns r, g, and b in the set [0, 255].
*
* #param h The hue
* #param s The saturation
* #param l The lightness
* #return int array, the RGB representation
*/
public static int[] hslToRgb(float h, float s, float l) {
// i added this sysout line
System.out.println("HSL(" + h + "," + s + "," + l + ")");
h /= 359.0;
s /= 100.0;
l /= 100.0;
float r, g, b;
if (s == 0f) {
r = g = b = l; // achromatic
} else {
float q = l < 0.5f ? l * (1 + s) : l + s - l * s;
float p = 2 * l - q;
r = hueToRgb(p, q, h + 1f / 3f);
g = hueToRgb(p, q, h);
b = hueToRgb(p, q, h - 1f / 3f);
}
int[] rgb = { to255(r), to255(g), to255(b) };
// and i added this to print it, don't know if its the best way to do it
System.out.print("RGB(");
for (int i = 0; i < rgb.length; i++) {
if ((i + 1) != rgb.length) {
System.out.print(rgb[i] + ",");
} else {
System.out.print(rgb[i]);
}
}
System.out.println(")");
return rgb;
}
public static int to255(float v) {
return (int) Math.min(255, 256 * v);
}
/** Helper method that converts hue to rgb */
public static float hueToRgb(float p, float q, float t) {
if (t < 0f)
t += 1f;
if (t > 1f)
t -= 1f;
if (t < 1f / 6f)
return p + (q - p) * 6f * t;
if (t < 1f / 2f)
return q;
if (t < 2f / 3f)
return p + (q - p) * (2f / 3f - t) * 6f;
return p;
}
}
I would like to know if it is possible to make this algorithm iterative instead of recursive, and if its posible, could someone help me?.
public static double adaptiveQuadrature(double a, double b) {
double h = b - a;
double c = (a + b) / 2.0;
double d = (a + c) / 2.0;
double e = (b + c) / 2.0;
double Q1 = h / 6 * (f(a) + 4 * f(c) + f(b));
double Q2 = h / 12 * (f(a) + 4 * f(d) + 2 * f(c) + 4 * f(e) + f(b));
if (Math.abs(Q2 - Q1) <= EPSILON)
return Q2 + (Q2 - Q1) / 15;
else
return adaptiveQuadrature(a, c) + adaptiveQuadrature(c, b);
}
static double f(double x) {
return Math.exp( - x * x / 2) / Math.sqrt(2 * Math.PI);
}
Thank you so much for your help!
I don't think so. The size of the steps is depending on function evaluations made at the endpoints of the initial interval, then at the endpoints of subintervals. The pattern is not progressive and you can't organize a single loop that will "guess" the step ahead of time.
Of course you can derecursivate by means of an explicit stack, but that won't essentially change the nature of the process.
is supposed to calculate the coordinates of a projectile launched with respect to time (steps of 100ms), with a linear equation, and it outputs linear numbers, but if i plot this equation with CalcMe.com (math tool) it makes a parabolic plot
InVel = Double.parseDouble(jTextField1.getText());
g = Double.parseDouble(jTextField8.getText());
y = 1;
while(y >= -1) {
t += 100;
x = InVel * TimeUnit.MILLISECONDS.toSeconds(t) * Math.cos(45);
y = InVel * TimeUnit.MILLISECONDS.toSeconds(t) * Math.sin(45) - (1 / 2) * g * Math.pow(TimeUnit.MILLISECONDS.toSeconds(t), 2);
//System.out.print(Double.toString(x));
//System.out.printf(" ");
System.out.print(Double.toString(y));
System.out.printf("%n");
}
jTextField6.setText(Double.toString(x));
the code is in java
g is constant (9.8)
and invel is given by user so its constant too
g is the gravity and invel the initial velocity of the projectile
the equation is:x=invel*time*cos(45) and y=invel*time*sin(45)-(1/2)*g*t^2
anyone can help me?
Your milisecond to second value conversion method TimeUnit.MILLISECONDS.toSeconds(t) is the main fact. Its returning long value which one you are wanted double. Please take a look on below code. Probably its your answer. Just replace hard-coded value with your jTextField
public static void main(String[] args) {
double InVel = Double.parseDouble("10.555");
double g = Double.parseDouble("9.8");
double y = 1;
double x=0;
double t=0;
while(y >= -1) {
t += 100;
double timeInSeconds = (t / (double)1000) % (double)60;
x = InVel * timeInSeconds * Math.cos(45);
y = InVel * timeInSeconds * Math.sin(45) - ((double) 1 / (double) 2) * g * Math.pow(timeInSeconds, 2);
//System.out.print(Double.toString(x));
//System.out.printf(" ");
System.out.println("X = " + x + " Y = " + Double.toString(y));
System.out.printf("%n");
}
}
I'm attempting to follow some psuedo code for solving cubic equations in Mathematics and Physics for Programmers, Chapter 3, as far as I can see I've followed it accurately, but I don't seem to be getting correct outputs.
For example: According to Wolfram Alpha 5x^3 + 4x^2 + 3x + 2 = 0 should give a root of x≈-0.72932, but I'm getting back -1.8580943294965526 from my script.
Can someone help me to work out what the hell I'm doing? I'm following the scripts to get a better understanding of maths and converting equations to code. But this is at the brink of my understanding so I'm finding it troublesome to debug. Coupled with the fact the book has no errata and many online reviews state the book has many errors, I'm struggling to see whether the issue is with my code, the books explanation or both.
The equation given in the book is:
Then if the discriminant > 0 then root has value of r+s:
if discriminant == 0 then there are two roots:
if discriminant < 0 you can find three roots as follows:
After finding t you can transform it to x by taking:
package com.oacc.maths;
public class SolveCubic {
public static double[] solveCubic(double a, double b, double c, double d) {
double[] result;
if (d != 1) {
a = a / d;
b = b / d;
c = c / d;
}
double p = b / 3 - a * a / 9;
double q = a * a * a / 27 - a * b / 6 + c / 2;
double D = p * p * p + q * q;
if (Double.compare(D, 0) >= 0) {
if (Double.compare(D, 0) == 0) {
double r = Math.cbrt(-q);
result = new double[2];
result[0] = 2 * r;
result[1] = -r;
} else {
double r = Math.cbrt(-q + Math.sqrt(D));
double s = Math.cbrt(-q - Math.sqrt(D));
result = new double[1];
result[0] = r + s;
}
} else {
double ang = Math.acos(-q / Math.sqrt(-p * p * p));
double r = 2 * Math.sqrt(-p);
result = new double[3];
for (int k = -1; k <= 1; k++) {
double theta = (ang - 2 * Math.PI * k) / 3;
result[k + 1] = r * Math.cos(theta);
}
}
for (int i = 0; i < result.length; i++) {
result[i] = result[i] - a / 3;
}
return result;
}
public static double[] solveCubic(double a, double b, double c) {
double d = 1;
return solveCubic(a, b, c, d);
}
public static void main(String args[]) {
double[] result = solveCubic(5, 4, 3, 2);
for (double aResult : result) {
System.out.println(aResult);
}
}
}
I also found this code example from the book site(n.b. this is not the psuedo code from the book): http://www.delmarlearning.com/companions/content/1435457331/files/index.asp?isbn=1435457331
on solveCubic(a,b,c,d)
--! ARGUMENTS:
a, b, c, d (all numbers). d is optional (default is 1)
--!
RETURNS: the list of solutions to dx^3+ax^2+bx+c=0
-- if d is defined then divide a, b and c by d
if not voidp(d)
then
if d=0 then return solveQuadratic(b,c,a)
set d to float(d)
set a to a/d
set b to b/d
set
c to c/d
else
set a to float(a)
set b to float(b)
set c to float(c)
end if
set p to b/3 - a*a/9
set q to a*a*a/27 - a*b/6 + c/2
set disc to p*p*p + q*q
if abs(disc)<0.001 then
set r to cuberoot(-q)
set ret to [2*r, -r]
else if disc>0 then
set r to cuberoot(-q+sqrt(disc))
set s to cuberoot(-q-sqrt(disc))
set ret to [r+s]
else
set ang to acos(-q/sqrt(-p*p*p))
set r to 2*sqrt(-p)
set ret to []
repeat with k=-1 to 1
set theta
to (ang - 2*pi*k)/3
ret.add(r*cos(theta))
end repeat
end if
set ret to ret-a/3 --NB: this adds the value to each
element
return ret
end
The error appears to be with the names of the parameters of your solveCubic method.
It seems your book is explaining how to solve the equation x3 + ax2 + bx + c = 0. You are calling your method thinking that the parameters a, b, c and d are for the equation ax3 + bx2 + cx + d = 0. However, it turns out that the body of your method is actually finding solutions to the equation dx3 + ax2 + bx + c = 0.
Aside from this naming error, the calculations appear to be correct. Try plugging your value ≈-1.858 into 2x3 + 5x2 + 4x + 3 if you don't believe me.
If you instead declare your solveCubic method as
public static double[] solveCubic(double d, double a, double b, double c) {
the parameters then correspond to the equation dx3 + ax2 + bx + c. You should then find that your method gives you the answer you expect.
Okay. So, first off the equations from the book seem to be referring to this idea: If you have an equation of the form:
Then by defining t as x - (a/3) you can transform this into an equation with no quadratic term, as verified by a bit of Mathematica:
Once you have no quadratic term, you can then apply the method given; let q be half the constant term, let p be one third the coefficient on the first power term, and define D (discriminant) as p*p*p - q*q.
All else then follows.
So why does your code not work? Because you've mislabeled the variables. a is the coefficient on x^2, not on x^3. If you call your method with the arguments (0.8, 0.6, 0.4, 1) or equivalently with (4, 3, 2, 5), you'll get the right answer.
(Or do as the other answer suggests and more around the variable names in the method declaration)
This works 100%. It has been tried and tested for all combinations.
public void solveCubicEquation(int A, int B, int C, int D) {
double a = (double) B / A;
double b = (double) C / A;
double c = (double) D / A;
System.out.println("Double values: ");
System.out.println(a + " " + b + " " + c);
double p = b - ((a * a) / 3.0);
double q = (2 * Math.pow(a, 3) / 27.0) - (a * b / 3.0) + c;
double delta = (Math.pow(q, 2) / 4) + (Math.pow(p, 3) / 27);
if (delta > 0.001) {
double mt1, mt2;
double t1 = (-q / 2.0) + Math.sqrt(delta);
double t2 = (-q / 2.0) - Math.sqrt(delta);
if (t1 < 0) {
mt1 = (-1) * (Math.pow(-t1, (double) 1 / 3));
} else {
mt1 = (Math.pow(t1, (double) 1 / 3));
}
if (t2 < 0) {
mt2 = (-1) * (Math.pow(-t2, (double) 1 / 3));
} else {
mt2 = (Math.pow(t2, (double) 1 / 3));
}
x1 = mt1 + mt2 - (a / 3.0);
} else if (delta < 0.001 && delta > -0.001) {
if (q < 0) {
x1 = 2 * Math.pow(-q / 2, (double) 1 / 3) - (a / 3);
x2 = -1 * Math.pow(-q / 2, (double) 1 / 3) - (a / 3);
} else {
x1 = -2 * Math.pow(q / 2, (double) 1 / 3) - (a / 3);
x2 = Math.pow(q / 2, (double) 1 / 3) - (a / 3);
}
} else {
System.out.println("here");
x1 = (2.0 / Math.sqrt(3)) * (Math.sqrt(-p) * Math.sin((1 / 3.0) * Math.asin(((3 * Math.sqrt(3) * q) / (2 * Math.pow(Math.pow(-p, (double) 1 / 2), 3)))))) - (a / 3.0);
x2 = (-2.0 / Math.sqrt(3)) * (Math.sqrt(-p) * Math.sin((1 / 3.0) * Math.asin(((3 * Math.sqrt(3) * q) / (2 * Math.pow(Math.pow(-p, (double) 1 / 2), 3)))) + (Math.PI / 3))) - (a / 3.0);
x3 = (2.0 / Math.sqrt(3)) * (Math.sqrt(-p) * Math.cos((1 / 3.0) * Math.asin(((3 * Math.sqrt(3) * q) / (2 * Math.pow(Math.pow(-p, (double) 1 / 2), 3)))) + (Math.PI / 6))) - (a / 3.0);
}
}
Note: will not work for imaginary values
This question already has answers here:
What's wrong with this division? [duplicate]
(6 answers)
Closed 8 years ago.
If I want to calculate 76/266 = 28.57% in java, what's the best data type to use?
So far, I have:
int x = 76;
int y = 266;
float z = (x * 100) / y;
But doing this, I get 28.0 as an answer. I need to get an answer rounded to the nearest hundredth place. Thanks.
In Java and some other programming languages, there is something called integer arithmetic, which says that if you do (in your case):
int / int = int
In your code, you are doing
(int * int) / int <=> int / int = int
Solutions:
Method 1: Something you can do to get a float is to use a float operand. In your case it can be the 100:
float z = (x * 100.0f) / y;
Here, the operation is
(int * float) / int <=> float / int = float
Method 2: Another way to solve this is to cast an integer to a float:
float z = (x * 100) / (float)y; // int * int / float = float
float z = (float)x * 100 / y; // float * int / int = float
Method 3: As #webSpider mentioned in his answer, you can just declare the variables x and y as float to avoid these problems.
Edit: To round your float result, you can try this:
float z = Math.round(result * 100) / 100f;
where the number of zeros of 100 is the number of decimal places. Note that 100f will be a float because of the postfix f.
float x = 76;
float y = 266;
float z = x * 100 / y;
//=28.571428
If you want to round it, use:
double x = 76;
double y = 266;
double z = Math.round(x * 100 / y* 100.0) / 100.0;
//=28.57
btw, as you see you don't need the parenthesis in your calculation there is a operator precedence ...
Maybe you can use java.math.BigDecimal for your calculation. I believe this is the highest precision datatype in Java
BigDecimal d1 = new BigDecimal(67.67);
BigDecimal d2 = new BigDecimal(67.68);
BidDecimal d3 = d1.divide(d2); // d1 + d2 is invalid
What you are doing in your code is,
multiply an integer x to 100 and then divide the result by integer y. So their output will be integer only.
Then you are storing this int result in a float variable. So it just adds .0 to your result.
To get the result you want you can do any of the following,
1. int x = 76;
int y = 266;
float z = (x * 100.0f) / y;
Note do not write 100.0 because it will be treated as a double number so you will get loss of precision error
2. float x = 76;
int y = 266;
float z = (x * 100) / y;
3. float x = 76;
float y = 266;
float z = (x * 100) / y;