how to solve cos 90 problem in java? [duplicate] - java

This question already has answers here:
Why does floating-point arithmetic not give exact results when adding decimal fractions?
(31 answers)
Closed 6 years ago.
I have some problems with calculating cosinus 90 in Java using Math.cos function :
public class calc{
private double x;
private double y;
public calc(double x,double y){
this.x=x;
this.y=y;
}
public void print(double theta){
x = x*Math.cos(theta);
y = y*Math.sin(theta);
System.out.println("cos 90 : "+x);
System.out.println("sin 90 : "+y);
}
public static void main(String[]args){
calc p = new calc(3,4);
p.print(Math.toRadians(90));
}
}
When I calculate cos90 or cos270, it gives me absurb values. It should be 0. I tested with 91 or 271, gives a near 0 which is correct.
what should I do to make the output of cos 90 = 0? so, it makes the output x = 0 and y = 4.
Thankful for advice

What you're getting is most likely very, very small numbers, which are being displayed in exponential notation. The reason you're getting them is because pi/2 is not exactly representable in IEEE 754 notation, so there's no way to get the exact cosine of 90/270 degrees.

Just run your source and it returns:
cos 90 : 1.8369701987210297E-16
sin 90 : 4.0
That's absolutely correct. The first value is nearly 0. The second is 4 as expected.
3 * cos(90°) = 3 * 0 = 0
Here you have to read the Math.toRadians() documentation which says:
Converts an angle measured in degrees to an approximately equivalent angle measured in radians. The conversion from degrees to radians is generally inexact.
Update: You can use for example the MathUtils.round() method from the Apache Commons repository and round the output to say 8 decimals, like this:
System.out.println("cos 90 : " + MathUtils.round(x, 8));
That will give you:
cos 90 : 0.0
sin 90 : 4.0

Try this:
public class calc
{
private double x;
private double y;
public calc(double x,double y)
{
this.x=x;
this.y=y;
}
public void print(double theta)
{
if( ((Math.toDegrees(theta) / 90) % 2) == 1)
{
x = x*0;
y = y*Math.sin(theta);
}
else if( ((Math.toDegrees(theta) / 90) % 2) == 0)
{
x = x*Math.cos(theta);
y = y*0;
}
else
{
x = x*Math.cos(theta);
y = y*Math.sin(theta);
}
System.out.println("cos 90 : "+x);
System.out.println("sin 90 : "+y);
}
public static void main(String[]args)
{
calc p = new calc(3,4);
p.print(Math.toRadians(90));
}
}

Related

Calculating degrees to radians in terms of pi

I made a code converting degrees to radians following my teacher's format but I want to try to make it in terms of pi. Right now when I plug in 30 as my degrees the output is a loooong decimal but I want it to come out as pi/6. Is there a way to keep the pi symbol in the output?
This is my current code:
public static double convertDeg(double deg)
{
double rad = deg * (Math.PI/180);
return rad;
}
and
System.out.println("Degrees to radians: "+Calculate.convertDeg(30));
The output is: "Degrees to radians: 0.5235987755982988"
"but I want it to come out as pi/6."
To get this format; Try this.
public static String convertDeg(double deg)
{
String rad = "Math.PI/"+(180/deg);
return rad;
}
It returns a string as the method return type is string.
It does'nt exactly return "pi/6" but "Math.PI/6".
So get the idea for its use from this;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
class HelloWorld {
public static String convertDeg(double deg)
{
String rad = "Math.PI/"+(180/deg);
return rad;
}
public static void main(String[] args) {
ScriptEngine engine = new ScriptEngineManager().getEngineByExtension("js");
try {
Object result = engine.eval(convertDeg(30));
System.out.println("\nDegree to Radian = "+result);
}
catch (ScriptException e) {
// Something went wrong
e.printStackTrace();
}
}
}
Its answer is as follows,
Degree to Radian = 0.5235987755982988
You can't set formatting up to convert degrees to radians with pi out of the box in java, but you can write your own function to do this.
We know that
360 degrees = 2 * PI radians =>
180 degrees = PI radians =>
1 degree = PI / 180 radians =>
Therefore
X degrees = PI * (X / 180) radians
In case degrees is an integer value
we can simplify a fraction X / 180
if gcd(X, 180) > 1, gcd -- the greater common divider.
X / 180 = (X / gcd(X, 180)) / (180 / gcd(X, 180))
The code is something like this (don't forget to check corner cases):
String formatDegreesAsFractionWithPI(int degrees) {
int gcd = gcd(degrees, 180);
return "(" + (degrees / gcd) + " / " + (180 / gcd) + ") * PI"
}
int gcd(int a, int b) = { ... }
In case degrees is a floating point number,
the problem is more complicated and my advice
is to read about 'converting decimal floating
point number to integers fraction'.
Related questions: gcd in java, convert float to fraction (maybe works)

What is the range of improved Perlin noise?

I'm trying to find the theoretical output range of improved Perlin noise for 1, 2 and 3 dimensions. I'm aware of existing answers to this question, but they don't seem to accord with my practical findings.
If n is the number of dimensions then according to [1] it should be [-sqrt(n/4), sqrt(n/4)]. According to [2] (which refers to [3]) it should be [-0.5·sqrt(n), 0.5·sqrt(n)] (which amounts to the same thing).
This means that the ranges should be approximately:
Dimensions
Range
1
[-0.5, 0.5]
2
[-0.707, 0.707]
3
[-0.866, 0.866]
However when I run the following code (which uses Ken Perlin's own reference implementation of improved noise from his website), I get higher values for 2 and 3 dimensions, namely approximately:
Dimensions
Range
1
[-0.5, 0.5]
2
[-0.891, 0.999]
3
[-0.997, 0.999]
With different permutations I even sometimes get values slightly over 1.0 for 3 dimensions, and for some strange reason one of the bounds for two dimension always seems to be about 0.89 while the other is about 1.00.
I can't figure out whether this is due to a bug in my code (I don't see how since this is Ken Perlin's own code) or due to those discussions not being correct or not being applicable somehow, in which case I would like to know what the theoretical ranges are for improved Perlin noise.
Can you replicate this? Are the results wrong, or can you point me to a discussion of the theoretical values that accords with this outcome?
The code:
public class PerlinTest {
public static void main(String[] args) {
double lowest1DValue = Double.MAX_VALUE, highest1DValue = -Double.MAX_VALUE;
double lowest2DValue = Double.MAX_VALUE, highest2DValue = -Double.MAX_VALUE;
double lowest3DValue = Double.MAX_VALUE, highest3DValue = -Double.MAX_VALUE;
final Random random = new SecureRandom();
for (int i = 0; i < 10000000; i++) {
double value = noise(random.nextDouble() * 256.0, 0.0, 0.0);
if (value < lowest1DValue) {
lowest1DValue = value;
}
if (value > highest1DValue) {
highest1DValue = value;
}
value = noise(random.nextDouble() * 256.0, random.nextDouble() * 256.0, 0.0);
if (value < lowest2DValue) {
lowest2DValue = value;
}
if (value > highest2DValue) {
highest2DValue = value;
}
value = noise(random.nextDouble() * 256.0, random.nextDouble() * 256.0, random.nextDouble() * 256.0);
if (value < lowest3DValue) {
lowest3DValue = value;
}
if (value > highest3DValue) {
highest3DValue = value;
}
}
System.out.println("Lowest 1D value: " + lowest1DValue);
System.out.println("Highest 1D value: " + highest1DValue);
System.out.println("Lowest 2D value: " + lowest2DValue);
System.out.println("Highest 2D value: " + highest2DValue);
System.out.println("Lowest 3D value: " + lowest3DValue);
System.out.println("Highest 3D value: " + highest3DValue);
}
static public double noise(double x, double y, double z) {
int X = (int)Math.floor(x) & 255, // FIND UNIT CUBE THAT
Y = (int)Math.floor(y) & 255, // CONTAINS POINT.
Z = (int)Math.floor(z) & 255;
x -= Math.floor(x); // FIND RELATIVE X,Y,Z
y -= Math.floor(y); // OF POINT IN CUBE.
z -= Math.floor(z);
double u = fade(x), // COMPUTE FADE CURVES
v = fade(y), // FOR EACH OF X,Y,Z.
w = fade(z);
int A = p[X ]+Y, AA = p[A]+Z, AB = p[A+1]+Z, // HASH COORDINATES OF
B = p[X+1]+Y, BA = p[B]+Z, BB = p[B+1]+Z; // THE 8 CUBE CORNERS,
return lerp(w, lerp(v, lerp(u, grad(p[AA ], x , y , z ), // AND ADD
grad(p[BA ], x-1, y , z )), // BLENDED
lerp(u, grad(p[AB ], x , y-1, z ), // RESULTS
grad(p[BB ], x-1, y-1, z ))),// FROM 8
lerp(v, lerp(u, grad(p[AA+1], x , y , z-1 ), // CORNERS
grad(p[BA+1], x-1, y , z-1 )), // OF CUBE
lerp(u, grad(p[AB+1], x , y-1, z-1 ),
grad(p[BB+1], x-1, y-1, z-1 ))));
}
static double fade(double t) { return t * t * t * (t * (t * 6 - 15) + 10); }
static double lerp(double t, double a, double b) { return a + t * (b - a); }
static double grad(int hash, double x, double y, double z) {
int h = hash & 15; // CONVERT LO 4 BITS OF HASH CODE
double u = h<8 ? x : y, // INTO 12 GRADIENT DIRECTIONS.
v = h<4 ? y : h==12||h==14 ? x : z;
return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
}
static final int p[] = new int[512], permutation[] = { 151,160,137,91,90,15,
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
};
static { for (int i=0; i < 256 ; i++) p[256+i] = p[i] = permutation[i]; }
}
Ken’s not using unit vectors. As [1] says, with my emphasis:
Third, there are many different ways to select the random vectors at the grid cell corners. In Improved Perlin noise, instead of selecting any random vector, one of 12 vectors pointing to the edges of a cube are used instead. Here, I will talk strictly about a continuous range of angles since it is easier – however, the range of value of an implementation of Perlin noise using a restricted set of vectors will never be larger. Finally, the script in this repository assumes the vectors are of unit length. If they not, the range of value should be scaled according to the maximum vector length. Note that the vectors in Improved Perlin noise are not unit length.
For Ken’s improved noise, the maximum vector length is 1 in 1D and √2 in 2D, so the theoretical bounds are [−0.5, 0.5] in 1D and [−1, 1] in 2D. I don’t know why you’re not seeing the full range in 2D; if you shuffled the permutation I bet you would sometimes.
For 3D, the maximum vector length is still √2, but the extreme case identified by [1] isn’t a possible output, so the theoretical range of [−√(3/2), √(3/2)] is an overestimate. These folks tried to work it out exactly, and yes, the maximum absolute value does seem to be strictly greater than 1.

How do I fix this heart?

Seeing as Valentine's Day is fast approaching, I decided to create a heart. So I found this heart from mathematica.se:
I played around in Mathematica (solved for z, switching some variables around) to get this equation for the z-value of the heart, given the x and y values (click for full-size):
I faithfully ported this equation to Java, dealing with a couple out-of-bounds cases:
import static java.lang.Math.cbrt;
import static java.lang.Math.pow;
import static java.lang.Math.sqrt;
...
public static double heart(double xi, double yi) {
double x = xi;
double y = -yi;
double temp = 5739562800L * pow(y, 3) + 109051693200L * pow(x, 2) * pow(y, 3)
- 5739562800L * pow(y, 5);
double temp1 = -244019119519584000L * pow(y, 9) + pow(temp, 2);
//
if (temp1 < 0) {
return -1; // this is one possible out of bounds location
// this spot is the location of the problem
}
//
double temp2 = sqrt(temp1);
double temp3 = cbrt(temp + temp2);
if (temp3 != 0) {
double part1 = (36 * cbrt(2) * pow(y, 3)) / temp3;
double part2 = 1 / (10935 * cbrt(2)) * temp3;
double looseparts = 4.0 / 9 - 4.0 / 9 * pow(x, 2) - 4.0 / 9 * pow(y, 2);
double sqrt_body = looseparts + part1 + part2;
if (sqrt_body >= 0) {
return sqrt(sqrt_body);
} else {
return -1; // this works; returns -1 if we are outside the heart
}
} else {
// through trial and error, I discovered that this should
// be an ellipse (or that it is close enough)
return Math.sqrt(Math.pow(2.0 / 3, 2) * (1 - Math.pow(x, 2)));
}
}
The only problem is that when temp1 < 0, I cannot simply return -1, like I do:
if (temp1 < 0) {
return -1; // this is one possible out of bounds location
// this spot is the location of the problem
}
That's not the behavior of the heart at that point. As it is, when I try to make my image:
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import static java.lang.Math.cbrt;
import static java.lang.Math.pow;
import static java.lang.Math.sqrt;
public class Heart {
public static double scale(int x, int range, double l, double r) {
double width = r - l;
return (double) x / (range - 1) * width + l;
}
public static void main(String[] args) throws IOException {
BufferedImage img = new BufferedImage(1000, 1000, BufferedImage.TYPE_INT_RGB);
// this is actually larger than the max heart value
final double max_heart = 0.679;
double max = 0.0;
for (int x = 0; x < img.getWidth(); x++) {
for (int y = 0; y < img.getHeight(); y++) {
double xv = scale(x, img.getWidth(), -1.2, 1.2);
double yv = scale(y, img.getHeight(), -1.3, 1);
double heart = heart(xv, yv); //this isn't an accident
// yes I don't check for the return of -1, but still
// the -1 values return a nice shade of pink: 0xFFADAD
// None of the other values should be negative, as I did
// step through from -1000 to 1000 in python, and there
// were no negatives that were not -1
int r = 0xFF;
int gb = (int) (0xFF * (max_heart - heart));
int rgb = (r << 16) | (gb << 8) | gb;
img.setRGB(x, y, rgb);
}
}
ImageIO.write(img, "png", new File("location"));
}
// heart function clipped; it belongs here
}
I get this:
Look at that dip at the top! I tried changing that problematic -1 to a .5, resulting in this:
Now the heart has horns. But it becomes clear where that problematic if's condition is met.
How can I fix this problem? I don't want a hole in my heart at the top, and I don't want a horned heart. If I could clip the horns to the shape of a heart, and color the rest appropriately, that would be perfectly fine. Ideally, the two sides of the heart would come together as a point (hearts have a little point at the join), but if they curve together like shown in the horns, that would be fine too. How can I achieve this?
The problem is simple. If we look at that horseshoe region, we get imaginary numbers. For part of it, it should belong to our heart. In that region, if we were to evaluate our function (by math, not by programming), the imaginary parts of the function cancel. So it should look like this (generated in Mathematica):
Basically, the function for that part is almost identical; we just have to do arithmetic with complex numbers instead of real numbers. Here's a function that does exactly that:
private static double topOfHeart(double x, double y, double temp, double temp1) {
//complex arithmetic; each double[] is a single number
double[] temp3 = cbrt_complex(temp, sqrt(-temp1));
double[] part1 = polar_reciprocal(temp3);
part1[0] *= 36 * cbrt(2) * pow(y, 3);
double[] part2 = temp3;
part2[0] /= (10935 * cbrt(2));
toRect(part1, part2);
double looseparts = 4.0 / 9 - 4.0 / 9 * pow(x, 2) - 4.0 / 9 * pow(y, 2);
double real_part = looseparts + part1[0] + part2[0];
double imag_part = part1[1] + part2[1];
double[] result = sqrt_complex(real_part, imag_part);
toRect(result);
// theoretically, result[1] == 0 should work, but floating point says otherwise
if (Math.abs(result[1]) < 1e-5) {
return result[0];
}
return -1;
}
/**
* returns a specific cuberoot of this complex number, in polar form
*/
public static double[] cbrt_complex(double a, double b) {
double r = Math.hypot(a, b);
double theta = Math.atan2(b, a);
double cbrt_r = cbrt(r);
double cbrt_theta = 1.0 / 3 * (2 * PI * Math.floor((PI - theta) / (2 * PI)) + theta);
return new double[]{cbrt_r, cbrt_theta};
}
/**
* returns a specific squareroot of this complex number, in polar form
*/
public static double[] sqrt_complex(double a, double b) {
double r = Math.hypot(a, b);
double theta = Math.atan2(b, a);
double sqrt_r = Math.sqrt(r);
double sqrt_theta = 1.0 / 2 * (2 * PI * Math.floor((PI - theta) / (2 * PI)) + theta);
return new double[]{sqrt_r, sqrt_theta};
}
public static double[] polar_reciprocal(double[] polar) {
return new double[]{1 / polar[0], -polar[1]};
}
public static void toRect(double[]... polars) {
for (double[] polar: polars) {
double a = Math.cos(polar[1]) * polar[0];
double b = Math.sin(polar[1]) * polar[0];
polar[0] = a;
polar[1] = b;
}
}
To join this with your program, simply change your function to reflect this:
if (temp1 < 0) {
return topOfHeart(x, y, temp, temp1);
}
And running it, we get the desired result:
It should be pretty clear that this new function implements exactly the same formula. But how does each part work?
double[] temp3 = cbrt_complex(temp, sqrt(-temp1));
cbrt_complex takes a complex number in the form of a + b i. That's why the second argument is simply sqrt(-temp1) (notice that temp1 < 0, so I use - instead of Math.abs; Math.abs is probably a better idea). cbrt_complex returns the cube root of the complex number, in polar form: r eiθ. We can see from wolframalpha that with positive r and θ, we can write an n-th root of a complex numbers as follows:
And that's exactly how the code for the cbrt_complex and sqrt_complex work. Note that both take a complex number in rectangular coordinates (a + b i) and return a complex number in polar coordinates (r eiθ)
double[] part1 = polar_reciprocal(temp3);
It is easier to take the reciprocal of a polar complex number than a rectangular complex number. If we have r eiθ, its reciprocal (this follows standard power rules, luckily) is simply 1/r e-iθ. This is actually why we are staying in polar form; polar form makes multiplication-type operations easier, and addition type operations harder, while rectangular form does the opposite.
Notice that if we have a polar complex number r eiθ and we want to multiply by a real number d, the answer is as simple as d r eiθ.
The toRect function does exactly what it seems like it does: it converts polar coordinate complex numbers to rectangular coordinate complex numbers.
You may have noticed that the if statement doesn't check that there is no imaginary part, but only if the imaginary part is really small. This is because we are using floating point numbers, so checking result[1] == 0 will likely fail.
And there you are! Notice that we could actually implement the entire heart function with this complex number arithmetic, but it's probably faster to avoid this.

Calculating circular rotation required to match new angle

I have a data values which vary from +PI to -PI radian.
I need to get minimum rotation (in radians) required to go from old value to new value like:
float rotationRequired(float oldValue, float newValue){
return newValue - oldValue;
}
but simply subtracting won't do, because to go from -179 degree to +179 degree one does not need to rotate full circle around, just 2 degree clockwise. Because -PI = +PI in a circle are technically same rotation. Also the values can be in any range, i.e 740 = 360 + 360 + 20, hence only 20.
I'm thinking about breaking values into sin and cos values, subtract and then atan :
double oldY = Math.sin(oldValue);
double oldX = Math.cos(oldValue);
double newY = Math.sin(newValue);
double newX = Math.cos(newValue);
float delta = (float) Math.atan2( (newY - oldY),(newX - oldX) );
But still its not giving correct results, can anyone suggest another method ?
Just do the subtraction, and then limit the result to +/-180 by adding or subtracting 360 as necessary (the % operator may help here...)
I converted angles to degrees and used this method to suggest what minimum rotation is required and in what direction:
public static int suggestRotation(int o, int n){
//--convert to +0 to +360 range--
o = normalize(o);
n = normalize(n);
//-- required angle change --
int d1 = n - o;
//---other (360 - abs d1 ) angle change in reverse (opp to d1) direction--
int d2 = d1 == 0 ? 0 : Math.abs(360 - Math.abs(d1))*(d1/Math.abs(d1))*-1;
//--give whichever has minimum rotation--
if(Math.abs(d1) < Math.abs(d2)){
return d1;
}else {
return d2;
}
}
private static int normalize(int i){
//--find effective angle--
int d = Math.abs(i) % 360;
if(i < 0){
//--return positive equivalent--
return 360 - d;
}else {
return d;
}
}

Java - How to round up float (or BigDecimal ) value by 0.5?

Seems simple question but I really suck at math and few examples online I've searched seems not working for me. (the result just return the same value as input etc)
For instance.. but its in C not Java
Round to Next .05 in C
So my goal is I have %.1f format float or double or big decimal and wanting to round it up to nearest .5
example:
1.3 --> 1.5
5.5 --> 5.5
2.4 --> 2.5
3.6 --> 4.0
7.9 --> 8.0
I tried following example but didn't work :( below just output 1.3 which is original value. I wanted it to be 1.5
public class tmp {
public static void main(String[] args) {
double foo = 1.3;
double mid = 20 * foo;
System.out.println("mid " + mid);
double out = Math.ceil(mid);
System.out.println("out after ceil " + out);
System.out.printf("%.1f\n", out/20.0);
}
}
Here's a simple method:
public static float roundToHalf(float x) {
return (float) (Math.ceil(x * 2) / 2);
}
This doubles the value, takes its ceiling, and cuts it back in half.
Multiplying (and later dividing) by 2, not 20, should do the trick.
double nearestPoint5 = Math.ceil(d * 2) / 2;
The below formula does not work well for number like 2.16
public static float roundToHalf(float x) {
return (float) (Math.ceil(x * 2) / 2);
}
The correct answer should be 2.0, but the above method gives 2.5
The correct code should be:
public static double round(float d)
{
return 0.5 * Math.round(d * 2);
}
See the Big Decimal Javadoc about why a String is used in the constructor
public static double round(double d, int decimalPlace){
BigDecimal bd = new BigDecimal(Double.toString(d));
bd = bd.setScale(decimalPlace,BigDecimal.ROUND_HALF_UP);
return bd.doubleValue();
}
Without using a function, you can do
double rounded = (double)(long)(x * 2 + 0.5) / 2;
Note: this will round towards infinity.
Some of the other answers round incorrectly (Math.round should be used, not Math.floor or Math.ceil), and others only work for rounding to 0.5 (which is what the question asked, yes). Here's a simple method that correctly rounds to the nearest arbitrary double, with a check to assure that it's a positive number.
public static double roundToNearest(double d, double toNearest) {
if (toNearest <= 0) {
throw new IllegalArgumentException(
"toNearest must be positive, encountered " + toNearest);
}
return Math.round(d/toNearest) * toNearest;
}

Categories