I'm trying to make a program to simulate the solar system.
for(int i=0;i<1000;i++) {
double X=(160*Math.cos((2*PI*i)/365));
double Y=(160*Math.sin((2*PI*i)/365));
posX=Math.round(X);
posY=Math.round(Y);
cadre.repaint();
sleep(200);
}
f.setVisible(false);
To make my planets turning around the sun, I have a formula; the problem is that i have a double number with this formula, and i can't make him become an int (i tried floor(X), Math.round(X), doesn't work (error : incompatible types : possible lossy conversion from long to int)
[]
You'll see that it is not really java but he works as Java (it's some Javascool), so your advices will probably work for me!
When you convert a double to an int the compiler can't determine whether this is a safe operation or not. You have to use an explicit cast such as
double d = ...
int i = (int) d; // implicitly does a floor(d);
In Java 8 there is function to help detect whether the cast was safe (from a long at least) Math.toIntExact
int i = Math.toIntExact((long) d); // implicitly does a floor(d);
You can do this running the GUI Event Loop as a periodic task.
double X= 160*Math.cos(i * 2 * PI / 360);
double Y= 160*Math.sin(i * 2 * PI / 360);
posX = Math.toIntExact(Math.round(X));
posY = Math.toIntExact(Math.round(Y));
cadre.repaint();
// note you have to return so the image can actually be drawn.
Add cast to int like:
posX = (int) Math.round(X);
Related
My question is two-part.
Why does the following work fine in Eclipse? Isn't "Double" a class?
Double h = 2.5;
double j = 2;
Why does "Double" above give me an error when I don't assign a decimal value to it, but "double" is fine whether or not I assign a decimal value to it?
As was already mentioned, the term is autoboxing. The object wrappers for the primitive types will automatically convert.
As to your second part,
Double a = 2;
Doesn't work since 2 is not a double and the auto boxing only works between the same types. In this case 2 is an int.
But if you cast it.
Double a = (double)2;
works just fine.
double a = 2;
works because an int can be automatically converted to a double. But going the
other way doesn't work.
int a = 2.2; // not permitted.
Check out the Section on conversions. In the Java Language Specification. Warning that it can sometimes be difficult to read.
Amended Answer.
In java you can cast up or down or have narrowing or widening casts (going from a 32 bit to 16 bit) value is narrowing. But I tend to think about it is losing vs not losing something. In most cases if you have the potential to lose part of value in assignment, you need to cast, otherwise you don't (See exceptions at end). Here are some examples.
long a = 2; // 2 is an integer but going to a long doesn't `lose` precision.
int b = 2L; // here, 2 is a long and the assignment is not permitted. Even
// though a long 2 will fit inside an int, the cast is still
// required.
int b = (int)2L; // Fine, but clearly a contrived case
Same for floating point.
float a = 2.2f; // fine
double b = a; // no problem, not precision lost
float c = b; // can't do it, as it requires a cast.
double c = 2.2f; // a float to a double, again a not problem.
float d = 2.2; // 2.2 is a double by default so requires a cast or the float designator.
float d = (float)2.2;
Exceptions
No cast is required when converting from int to float or long to double. However, precision can still be lost since the floats only have 24 bits of precision and doubles only have 53 bits of precision.
To see this for ints you can run the following:
for (int i = Integer.MAX_VALUE; i > Integer.MAX_VALUE-100; i--) {
float s = i;
int t = (int)s; // normal cast required
if (i != t) {
System.out.println (i + " " + t);
}
}
Double is a wrapper class, creating a new Double casts a primitive variable of the SAME type into a Object. For Double h = 2, you are wrapping a int into a Double. Since wrapping only works between same types, if you want your Double variable be 2, then you should use
Double h = 2.0;
I looked and found one post which helped me here:
Convert Linear scale to Logarithmic
However I either did some mistake I can't find or I got wrong idea of the formula. I want to convert any number from linear 1-256 range to their respective values if it was logarithmic scale. Can someone help me to correct my code? When i try values low values from zero it works kind of fine but trying to convert anything over 160 gets me result which is > 256.
Here is my code:
package linear2log;
public class Linear2Log {
public static void main(String[] args) {
System.out.println("Ats3: " + lin2log(160));
}
public static long lin2log(int z) {
int x = 1;
int y = 256;
double b = Math.log(y/x)/(y-x);
double a = 10 / Math.exp(b*10);
double tempAnswer = a * Math.exp(b*z);
long finalAnswer = Math.max(Math.round(tempAnswer) - 1, 0);
return finalAnswer;
}
}
You get the formula wrong.
For sure this line
double a = 10 / Math.exp(b*10);
You are using value 10 from example, but you should be using your value which is 256.
double a = y / Math.exp(b * y);
I don't get why are you using this line:
long finalAnswer = Math.max(Math.round(tempAnswer) - 1, 0);
This way you are always getting value that is one less than actual value.
I am trying to convert some old DSP code written in C into Java and later to C#. I do not understand what the argument "double (*Window)(double)" means and how to reference it in the Java code. The following function has me unsure what to do.
void WinFirI(float LowOmega, float UppOmega,
float *Shape, int Len, double (*Window)(double), float shift)
{ int i; double time,phase,shape;
// printf("WinFirI: %5.3f %5.3f %d\n",LowOmega,UppOmega,Len);
for(i=0; i<Len; i++)
{ time=i+(1.0-shift)-(float)Len/2; phase=2*M_PI*time/Len;
if(time==0) shape=UppOmega-LowOmega;
else shape=(sin(UppOmega*time)-sin(LowOmega*time))/time;
// printf("%2d %5.1f %5.2f %7.4f %7.4f\n",i,time,phase,shape,(*Window) (phase));
Shape[i]=shape*(*Window)(phase)/M_PI; }
}
So far I have written this:
public void WinFirI(float LowOmega, float UppOmega,
float[] Shape, int Len, double[] Window, float shift) {
double time;
double phase;
double shape;
// printf("WinFirI: %5.3f %5.3f %d\n",LowOmega,UppOmega,Len);
for(int i=0; i<Len; i++) {
time = i +(1.0-shift) - (float)Len/2;
phase = 2 * Math.PI * time / Len;
if(time==0) {
shape = UppOmega - LowOmega;
}
else {
shape=(Math.sin(UppOmega*time) - Math.sin(LowOmega*time)) / time;
}
// printf("%2d %5.1f %5.2f %7.4f %7.4f\n",i,time,phase,shape, (*Window)(phase));
//Shape[i]=shape*(*Window)(phase)/M_PI;
Shape[i] = shape * Window[phase]/Math.PI;
}
}
Pointer to function with parameter double returning double.
As an added note, implementing this function pointer behavior in Java would be done through an anonymous class/interface.
double Window(double param);
In Java would be:
interface WindowFnWrapper {
double Window(double param);
}
Then the function signature would be:
public void WinFirI(float LowOmega, float UppOmega,
float[] Shape, int Len, WindowFnWrapper WindowWrapper, float shift)
Every time you call Window() you would replace it with WindowWrapper.Window().
The declaration double (*Window)(double) declares a parameter Window, whose value is a pointer to a function. That function must be one which takes a single double as an argument, and returns a double.
In your C code, (well, actually the commented-out part), that pointer gets dereferenced, and the function called, passing phase as its argument. That is, the value of the expression (*Window) (phase) is just the result of calling the function whose address you passed in.
If you're using Java 8 or above, the nearest available equivalent is the Function generic class, from the java.util.function package. So if you write
import java.util.function.Function;
then you can declare the parameter as
Function<Double,Double> window
and use it as
window.apply(phase);
The only real difference between this and your C code is that the type parameters to Java generics can't be primitive types such as double.
Double is a reference type that works a bit like double, except that a Double can be null, whereas a double can't. In effect, this should make no difference to your code, except that you may want to add some error handling to deal with the case where window.apply(phase) evaluates to null.
If I call
methodName(5, 1/2);
and it has the signature
public static int methodName(int x, double y){
}
does the methodName receive y with a value of 0 or 0.5?
int y = 1/2;
At this point, y is 0. If you try to cast it to a double afterwards it will be 0.0. It doesn't remember how it got its value, just what its value is.
EDIT: I think the compiler will actually replace 1/2 with 0 at compile time. Making the code literally identical to int y = 0
int y = 1/2;
In this code, y will be 0;
If you want to get it as 0.5
Have a try with the following code:
double y = 1.0 * 1 /2; //y is 0.5
It will evaluate to 0.
There's not a whole lot you can do with the above code.
There should be no specific reason to store y as an int.
Try this instead:
double y = 1/2.0;
int y = 1/2
Since you're using 1 (int) and 2 (int) to make the division, it's an integer division, thus y = 0 (and remainder (%) is 1).
I think you are confused with parameters (the parenthesis). In java every method has a set of parameters (they might not hold values ex: exampleMethod()).
A parameter is a variable that is passed into the method, so when in your code you call:
methodName() initialize it with methodName(x,y);
the x and y inside the method are just pointers for the values you pass through the parameters. I would suggest that you name your variables differently to avoid this confusion. For example:
int x;
int y;
methodName(int argX, double argY)
{
}
Also to answer your question, an int cuts off its stored value at the decimal point, so 5.9 would round to 5 rather than 6, so if you needed a floating point variable for y, either declare it as a float or a double, either will work, but most methods in the java library are written to take doubles as parameters rather than floats
I am trying to make a sequence of code that calculates the volume of a cone based on a user input height and radius (see below).
My problem is that the answer comes out wrong (but not by a long way). Using the example of height = 5, radius = 10, I get an answer from the code of 500 (treating pi as exactly 3), but calculating manually I get ~523.
I'm assuming it has something to do with the variable type I am declaring pi under (double then converting to long) but I have struggled to make any other combination of variable types work.
What is the correct version of this below that will store pi properly (to at least 5 or 6 dec places)?
double piDouble = Math.PI;
long height = Long.parseLong(heightString);
long pi = (new Double(piDouble)).longValue();
long radius = Long.parseLong(radiusString);
long volumeBase = (pi*(radius*radius)*height) / 3;
long pi = (new Double(piDouble)).longValue(); is a long, so it is equal to 3, exactly.
If you need more precision, use double all the way, and round at the end only. This should give you the result you expect:
double piDouble = Math.PI;
long height = Long.parseLong(heightString);
long radius = Long.parseLong(radiusString);
double volumeBase = (piDouble * (radius * radius) * height) / 3;
You can then round the result if you need to:
long roundedDownVolume = (long) volumeBase; //round down
long roundedVolume = Math.round(volumeBase); //or round to the closest long
You should use BigDecimal for this kind of arithmetic.