Java doing Math not as expected [duplicate] - java

This question already has answers here:
Why double width = 50/110000; the output is 0.000000000000000?
(3 answers)
Closed 9 years ago.
I have this really weird problem with Java. Basicly, this is what is going on:
int i = (int) Math.ceil((30 * 50) / 1000);
which would be the same as
int i = (int) Math.ceil(1.5);
but it doesn't return 2, it returns 1! However, the seccond line does return 2! This is really weird...
If it helps, here's the actual line of code:
pStats.setPlayerEnergy(
player,
pStats.getPlayerEnergy(player)
+ (int) Math.ceil((pStats.getPlayerFoodTick(player) * pStats
.getPlayerHydrationTick(player)) / 1000));
Does anyone have an idea what's going on here and how to fix it?

This is Integer division. In Java:
(30 * 50) / 1000 = 1
int i = (int) Math.ceil((30.0 * 50) / 1000);
Will give you the expected result.

integer/integer will give you the integer value make any value either denominator or numerator as float you will get the answer
int i = (int) Math.ceil((30 * 50) / 1000.0);
or
int i = (int) Math.ceil((30.0 * 50) / 1000);
or
int i = (int) Math.ceil((30 * 50.0) / 1000);

Related

Why does my float type-casting expression return two different values?

Here are the expressions I'm working with:
float firstValue = (float) (5 / 2); //output is 2.0
float secondValue = (float) 5 / 2; //output is 2.5
I'm stumped here and can't figure out why this type casting is returning two different values. I understand I can just do (5f / 2f) but I wanted to experiment using the other type casting with an expression. Why is firstValue 2.0 and secondValue 2.5? Where did the .5 go?
As brackets have the highest precedence, they get solved first
float firstValue = (float) (5 / 2); // division of integers
= (float) (2); // 5/2 = 2 , as Integers are being divided
= 2f
float secondValue = (float) 5 / 2; // division of float with integer
= ((float) 5) / 2;
= 5f / 2; // second value is equivalent to this
= 2.5f // as Float divided by Integer is Float
The first is integer math. This
float firstValue = (float) (5 / 2);
First divides five by two and gets two. Then it converts two to 2.0. The second is floating point math.
float secondValue = 5f / 2;
Which is 2.5 (and a float). Because a float divided by an int is a float.
float firstValue = (float) (5 / 2); // division of integers
The first step is to do 5/2 calculation.Then the answer is given in float.If you explain further 5 and 2 are int numbers. After calculating the int for two int numbers, the final answer is returned by int. Here the final int answer (2) is converted to a float answer. That is, wider conversion is used here. So the final answer is the integer value(2) shown in float form(2.0).
2.float secondValue = (float) 5 / 2; //output is 2.5
Since the first value(5) is named a float number, the final answer is the decimal itself

Is there a replacement for this double math

Is there a Java operator that would create a value equal to count but in fewer lines?
double theta = //Some value;
int count = 0;
while (theta > 0) {
theta -= pi * (1.0 / 8.0);
count += 1;
}
You've just implemented division by repeated subtraction.
So, if you had actual real numbers in Java, you could do ...
int result = (int) (theta / (Math.PI / 8)) + 1;
... to get the same result. However due to repeated rounding errors in your code, that has many more steps than a simple division, the answers will diverge a bit. The results will be the same for thetas up to around 55 million.
The rounding errors are there because float and double are not accurate representations of real numbers.
See also: Is floating point math broken?
Assuming theta > 0, something like this should work:
int count = (int)Math.ceil (theta/(Math.PI * (1.0 / 8.0)));
or
int count = (int)Math.ceil (theta*8/Math.PI);
How about this: Math.ceil( theta/(pi * (1.0 / 8.0)))?

How can I use Trigonometry and Pi correctly in Java [duplicate]

This question already has answers here:
Division of integers in Java [duplicate]
(7 answers)
Double value returns 0 [duplicate]
(3 answers)
Closed 5 years ago.
//Here is my method that I have created.
//I want my radius1 to equal "7.07" but once I use the method it gives me zero
public double getCircumscribedCircleRadius()
{
radius1 = 1 / 2 * 10 * 1 / Math.sin( Math.PI / 4);
return radius1;
}
You need to cast you result in double :
double radius1 = (double) 1 / 2 * 10 * 1 / Math.sin( Math.PI / 4);
output : 7.0710678118654755

How to put this equation in java code?

This is what I did but no matter what I keep getting infinity:
public double calcr(){
double cot = 1 / Math.tan(0);
return .5 * sideLength * cot * (Math.PI / numSides);
}
Main:
RegularPolygon poly = new RegularPolygon(4, 10);
System.out.println(poly.calcr());
Output:
Inifinity
What am I doing wrong?
The problem is that you do
double cot = 1 / Math.tan(0);
which will make cot be Infinity.
You'd want:
double cot = 1 / Math.tan(Math.PI / numSides);
return .5 * sideLength * cot;
Or, in a single line:
return .5 * sideLength / Math.tan(Math.PI / numSides);
tan(0) is 0, so this line
double cot = 1 / Math.tan(0);
sets cot to Infinity. The computation below it will then also evaluate to Infinity, as you saw.
Since it looks like you're trying to evaluate cot(pi/n), you'd need 1 / Math.tan(Math.PI / n) instead of using cot * (Math.PI / numSides) with an incorrect value for cot.

Mandelbrot very slow to refresh, any way to make it faster?

I've been working recently on a fractal generator, and have been specifically working on the Mandelbrot set. Unfortunately, zooming and moving seems to be very inneficient and takes quite a while to refresh. I am generating it every time I zoom, and I know this is probably not the most efficient way of doing this, and I can't seem to find code that uses another method that I understand.
These are the following methods I use, the first being an intial generation, the second being a refresh method.
private void genMandelbrot(Dimension size) {
for(int x=0;x<size.width;x++) {
for(int y=0;y<size.height;y++) {
double moveX=globalx;
double moveY=globalx;
//zoom and x/y offset.
double real = 1.5 * (x - size.width / 2) / (0.5 * zoom * size.width) + moveX;
double imaginary=(y - size.height / 2) / (0.5 * zoom * size.height) + moveY;
double newRe=0,newIm=0,oldRe=0,oldIm=0;
int i;
for(i=0;i<8000;i++) {
oldRe = newRe;
oldIm = newIm;
newRe = oldRe * oldRe - oldIm * oldIm + real;
newIm = 2 * oldRe * oldIm + imaginary;
if((newRe * newRe + newIm * newIm) > 4) break;
}
Cell c = new Cell(Color.getHSBColor(i % 256, i % 255, 255 * ((i<20)? 1:0)), new Dimension(1,1), new Point(x,y));
cells.add(c);
}
}
}
public void refreshMandelbrot(Dimension size) {
for(Cell c : cells) {
double moveX=globalx;
double moveY=globalx;
int x=c.x;
int y=c.y;
//zoom and x/y offset.
double real = 1.5 * (x - size.width / 2) / (0.5 * zoom * size.width) + moveX;
double imaginary=(y - size.height / 2) / (0.5 * zoom * size.height) + moveY;
double newRe=0,newIm=0,oldRe=0,oldIm=0;
int i;
for(i=0;i<8000;i++) {
oldRe = newRe;
oldIm = newIm;
newRe = oldRe * oldRe - oldIm * oldIm + real;
newIm = 2 * oldRe * oldIm + imaginary;
if((newRe * newRe + newIm * newIm) > 4) break;
}
cells.set(cells.indexOf(c), new Cell(Color.getHSBColor(i % 256, i % 255, 255 * ((i<20)? 1:0)), new Dimension(1,1), new Point(x,y)));
}
System.out.println("Set refreshed.");
}
I suppose that cells is some kind of List implementation?
In that case, the most time of your refresh method is spent in this line:
cells.set(cells.indexOf(c), new Cell(Color.getHSBColor(i % 256, i % 255, 255 * ((i<20)? 1:0)), new Dimension(1,1), new Point(x,y)));
More precisely in cells.indexOf(c), where the entire list is iterated to find the correct index of c.
Since you are just changing the colour of each cell, the easiest fix is to change the colour of the cell you are currently working with. I don't know the actual implementation of your Cell class, but if it had a method setColor(...), you could replace the above line with
c.setColor(Color.getHSBColor(i % 256, i % 255, 255 * ((i<20)? 1:0)));
This reduces the runtime of the refreshMandelbrot method to the same as for the genMandelbrot method.
I don't know the purpose of the Cell class, but if you are only using it as a wrapper for a colour, you might gain some more performance if you store the computed colours for each pixel in a two-dimensional array or write directly to a Graphics or Raster object instead of handling a flat list of cell wrappers.
Most likely you need to subdivide the fractal and compute the less interesting tiles less intense. 8000 repetiton is a lot. You can also simplify the calculation a bit.

Categories