Problems with dividing while using for loop - java

For some reason whenever I try to run this code, speed remains at 0 and it counts i up to x and then speed is suddenly changed to 1.0. speed is supposed to be a decimal of x depending on how many times the for-loop has run through. I don't understand why this is happening and would be very grateful for some clarity.
double speed;
int x = 200;
for(int i = 0; i <= x; i++){
speed = i/x;
System.out.println("Speed- " + speed);
System.out.println("Ticks- " + i);
}
for(int i = x; i >= 0; i--){
speed = i/x;
System.out.println("Speed- " + speed);
System.out.println("Ticks- " + i);
}

Try this:
double x = 200; // use a double instead of an int
The problem? you were dividing two ints, and the result is another int. By converting one of the two operands to a double, the division will now yield a number with decimals.

x must be an float variable in order to get the correct result. If both, i and x are integers, speed is an integer too, and that's the reason you get only 0 and 1

Related

for X terms, find P = (2! /1) + (!4/2) - (!6/3) ... and my code works for every test but one

For this formula:
I had to make a method to automate it, and I've received 4 examples to try it out.
x = 1 > p = 2
x = 3 > p = -226
x = 4 > p = 9854
however, when I insert 11 the answer should be 3.0198773447 and I receive -1.78316945E8 instead :/
here is my code:
System.out.println("Insira o numero: ");
int x = input.nextInt();
int fat = 1;
int contador = 0;
int contador1 = 0;
double p = 0;
for(double i = 1; i <=x; i++){
fat = 1;
contador++;
contador1 = contador* 2;
for(double j = 1; j <= contador1; j++){
fat *=j;
}
if(contador <=1){
p += fat / contador;
}
if(contador % 2 ==0 && contador > 1){
p += fat / contador;
}else if( contador % 2 != 0 && contador > 1){
p -= fat / contador;
}
}
System.out.println(p);
If you type in 11, that means contador1 will become as high as 22 (you will loop 11 times, every loop you first increment contador, and contador1 is twice that, so, 22. In other words, you'll end up having to calculate 22!.
The int type does not hold any arbitrary integer. It can only hold integers between -2^31 and +2^31-1. If you try to go beyond those bounds, it just loops around. Witness it in action:
int x = Integer.MAX_VALUE; // a constant representing 2^31-1.
int y = x + 1;
System.out.println(x);
System.out.println(y);
// Prints: 2147483647
// -2147483648
Where'd that minus come from? That's that whole 'loops around' thing. 22! is much lager than than this upper bound. Hence, your code doesn't work and it also explains why your algorithm tosses a negative number in there.
You could choose to use long instead which can hold it, but long, too, has limits - 2^63-1 to be precise. You could use double which goes ever further (up to about 1e308 which is a lot more than 2^63), but doubles are not accurate and the lack of accuracy gets worse as you move further away from 0. Past 2^53 or so, the distance between 2 representable numbers in the double range is more than 1, meaning, +1 no longer does anything (all operations on double values are rounded to the nearest representable double after every operation).
More generally trying to do 'math' on really large numbers is a non-trivial affair, and your basic + and / can no longer get the job done. Look up the API of BigDecimal which guarantees you perfect accuracy at the cost of, naturally, performance. You could use that, and get perfect answers. Though it'll take a while.

Stuck with calculating exponents in Java (Taylor Series) [duplicate]

This question already has answers here:
pow (x,y) in Java
(4 answers)
Closed 6 years ago.
I'm a bit stumped. I'm working on a homework question that requires you to find e^x through a series of 30 iterations: 1 + x + x^2/2! ... x^n/n!. In this case n = 30 and the range for x is -3 through 3. Seems straightforward enough. However when trying to execute it in Java I'm finding that I'm baffled.
The thought was to run two for loops. The outer loop for the iterations of x and the inner loop for the iterations for n. Here is the code so far:
double series = 1.0;
for (int x=-3; x<=3; x++)
{
for (int n=1; n<=x+30; n++)
{
series = series + (x^n)/n;
n*=n;
}
System.out.println(""+ x +"\t "+ (series+1));
}
Any advice would be greatly appreciated.
You might have to pay more attention to every single variable and the value changes inside the loops to better verify your code.
You have done a few mistakes:
multiplied n to itself and then divided by n as well. According to your formula you need to power the number by n, not nFactorial. Moreover nFactorial is a large number to be stored (and get accurate results), better use the advantage of dividing by n and multiplying by x at every step (see below code).
You have also used the XOR operator. Instead use the Math.pow() method.
You need to initialize the series value in each inner loop start.
If you started with initial value of 1, do not need to print (series+1) at end. Better initialize it to 0, or remove +1 in the print.
The following code would solve your purpose better.
double series = 1.0;
double term = 1.0;
for (int x = -3; x <= 3; x++) {
series = 1.0;
term = 1.0;
for (int n = 1; n <= 30; n++) {
term = (term * x / n);
series += term;
}
System.out.println("" + x + "\t " + (series));
}
you can write your formula with MATH.POW like this:
for (int x=-3; x<=3; x++)
{
for (int n=1; n<=x+30; n++)
{
series = series + (Math.pow(x,n)/n);
n*=n;
}
System.out.println(""+ x +"\t "+ (series+1));
}

Java For-loop changes numeric result when changing type of loop variable

I wrote a program to calculate the PI number with Leibniz formula:
[
I wrote a for-loop with type of initialization is "int" , the loop works fine but when i changed the initialization type to "long" the result is changed. This only happens when the loop times over a billion. This makes the "int - loop" calculates PI more accurate than "long - loop". I don't know why this happens. Please help me to understand this issue. Thanks! and here is my code.
public static void main(String[] args) {
double result1 = 0;
double result2 = 0;
double sign = 1;
for (int i = 0; i <= 1607702095; i++) {
result1 += sign/(2 * i + 1);
sign *= -1;
}
sign = 1;
for (long j = 0; j <= 1607702095; j++) {
result2 += sign/(2 * j + 1);
sign *= -1;
}
System.out.println("result1 " + result1 * 4);
System.out.println("result2 " + result2 * 4);
System.out.println("pi " + Math.PI);
}
And the result is:
result1 3.141592653576877
result2 3.1415926529660116
pi 3.141592653589793
Actually, your first loop would have int overflow in the calculation of (2 * i + 1) when i is large enough, so I wouldn't rely on the output of it.
The second loop, on the other hand, produces a more correct output, since (2 * j + 1) doesn't overflow, since it performs long multiplication.
This makes the "int - loop" calculates PI more accurate than "long - loop"
That's probably just a coincidence, since the calculations in the int loop overflow.
Because you are getting overflow at the line
result1 += sign/(2 * i + 1);
Where the value of 2*i cross the max integer value
int range is -2,147,483,648 to 2,147,483,647 but when you do 2*i for greater value it crosses that range.
Better to be stick with long and that gives you correct output.
2 * i when i is close to the end of your loop will overflow the max value for an int which is 2147483647.
Using a long that operation doesn't overflow.
The correct procedure is using a long type. Probably because values are added and removed around the correct PI for some strange behavior the overflows momentarily compute to a value closer to the right PI.
I suppose that change the limit of the for loop of few values will change the final result to a value that is more far from the right PI.
You have integer overflow.
The max capacity of a signed int is (2^31)-1, or 2,147,483,647.
(1,607,702,095 * 2) is 3215404190, which is bigger than 2,147,483,647.
When you change i to a long you increase the capacity of i to (2^63)-1.
Noticed everyone is pointig the integer overflow, but you might want a solution. (If you already have one, please ignore the following :) )
Having the overflow in the (2 * i + 1) part of the code, you should max the i in the for loop to (Integer.MAX_VALUE / 2 - 1), which results in:
for (int i = 0; i <= (Integer.MAX_VALUE / 2 - 1); i++) {
result1 += sign/(2 * i + 1);
sign *= -1;
}
You can also do that to the long part with (Long.MAX_VALUE / 2 - 1) but it will be running for a VERY LONG time.

double takes the value NaN after 0/0

I have this class that works on pixels of a sequence of images
private int makeRSR(int x, int y)
{
double bRed = 0;double bGreen = 0; double bBlue = 0;
for(int k: sequence.keySet())
{
BufferedImage img = sequence.get(k);
for(int i=0; i<iteration; i++){
for(int j=0;j<spray_int; j++){
int dist= ((int)(dis_int*Math.random()));
double theta=((int)(361*Math.random())) ;
double inc_x=dist * Math.cos((theta*(Math.PI/180)));
double inc_y=dist * Math.sin((theta*(Math.PI/180)));
int row=Math.abs((int)(inc_y+y));
int column=Math.abs((int)(inc_x+x));
if(row<1 || column<1 || row>altI-1 || column>largI-1){
row=Math.abs((int) ((altI-1)*Math.random()));
column=Math.abs((int) ((largI-1)*Math.random()));
}
Color c = new Color(img.getRGB(column,row));
red.add(c.getRed());
green.add(c.getGreen());
blue.add(c.getBlue());
}
Color c = new Color(img.getRGB(x,y));
red.add(c.getRed());
green.add(c.getGreen());
blue.add(c.getBlue());
double maxR=max(red);
double maxG=max(green);
double maxB=max(blue);
bRed += ((((double)c.getRed()) / (maxR))*255.00);
bGreen += ((((double)c.getGreen()) / (maxG))*255.00);
bBlue += ((((double)c.getBlue()) / (maxB))*255.00);
red.clear();green.clear();blue.clear();
}
}
redValue=0;greenValue=0;blueValue=0;
redValue= (int) (bRed/(iteration*(sequence.size())));
greenValue= (int) (bGreen/(iteration*(sequence.size())));
blueValue=(int) (bBlue/(iteration*(sequence.size())));
bRed=0.0;bGreen=0.0;bBlue=0.0;
return new Color(redValue,greenValue,blueValue).getRGB();
}
the problem is that sometimes c.getRed() and maxR are both 0 (same for the other channels) and so bRed loses its content and take value NaN, and it never change. Is there an error, something I missed, or do I have to prevent the 0/0 by adding a check?
Thanks, Bye
Since 0/0 is an undefined number you need to decide how do you want do treat it.
Find out why you get both 0 in current and max red values and prevent it.
Set result of division to 0 (or any number you decide to get the expected result) if both c.getRed() and maxR are 0.
Because dividing by zero is an error, it results in NaN, which stands for Not a Number. Subsequent operations involving NaN will also result in NaN, that's why it's value never changes afterwards.
You should explicitly check for zero divident before division to prevent division by zero.

Cause of comparing long slower than comparing double

I wrote a little program to calculate the first 18 triples (x,y,z) with x<y<z, which satisfy x^3+y^3=z^3+1.
While playing around to optimise the total runtime, I discovered, that using double for the cubic values and the two sides of the equation is faster than using long. On my machine the difference is about 3 seconds.
Now I wonder why exactly this is the case. I guess it is somewhere in the internal handling of long while the comparison of two long-Variables, as this is the only thing, which changes within the calculation loops.
Here is my code:
class Threes {
public static void main(String[] args) {
System.out.println("Threes --- Java");
int Z_MAX = 60000, Y_MAX = Z_MAX-1, X_MAX = Y_MAX-1;
double[] powers = new double[Z_MAX+1];
for (int i = 0; i <= Z_MAX; i++) {
powers[i] = Math.pow(i, 3);
}
System.out.println("Powers calculated");
int x, y, z;
double right, left;
int[][] sets = new int[18][3];
int foundCount = 0;
long loopCount = 0;
long start, end;
start = System.currentTimeMillis();
for (x = 1 ; x < X_MAX; x++) {
for (y = x + 1; y < Y_MAX; y++) {
right = powers[x] + powers[y];
for (z = y + 1; z < Z_MAX; z++) {
left = powers[z] + 1;
if (right < left) {
z = Z_MAX;
} else if (right == left) {
sets[foundCount][0] = x;
sets[foundCount][1] = y;
sets[foundCount][2] = z;
foundCount++;
end = System.currentTimeMillis();
System.out.println("found " + foundCount + ". set:\t" + x + "\t" + y + "\t" + z + "\t" + ((end - start) / 1000.0));
if (foundCount == 18) {
x = X_MAX;
y = Y_MAX;
z = Z_MAX;
}
}
loopCount++;
}
}
}
System.out.println("finished: " + loopCount);
}
}
The lines I changed are:
double[] powers = new double[Z_MAX+1];
becomes
long[] powers = new long[Z_MAX+1];
and
powers[i] = Math.pow(i, 3);
becomes
powers[i] = (long)Math.pow(i, 3);
and
double right, left;
becomes
long right, left;
"Bonus Question": What other possibilities of optimizing the whole code in terms of total runtime do I have? I know, that leaving out the loopCount gives me some milliseconds. I'm sure, that I have to reduce the number of loop iterations significantly. But how?
If you are using 32-bit operating system the performance for long-variable could be worse because long is 64-bit type. For example, with 64-bit OS Java could do the comparison with just one machine instruction, but in 32-bit environment it has to use multiple machine instructions, since it can only handle 32-bit at the time.
But for double, this is not neccessary the case, since 32-bit systems have machine instructions for 64-bit floating point numbers, even when thet don't have them for 64-bit integers.
Also, with code:
powers[i] = (long)Math.pow(i, 3);
there is two unneccesary conversions, first i (integer) is converted to double (that's what Math.pow takes) and then the return value is converted back to 64-bit integer (long).
It's probably fair to say that your code spends most of its time in this section:
for (z = y + 1; z < Z_MAX; z++) {
left = powers[z] + 1;
if (right < left) {
z = Z_MAX;
}
And most of the time, it will always be taking the same branch out of the conditional. So once your code has reached the steady-state (i.e. once the CPU's branch predictor is set up), the run-time will be dominated by the computation itself: dependencies are minimised, so the latency of the instruction pipeline doesn't matter.
On a 32-bit machine, doing addition and comparison on 64-bit integer types takes more instructions than doing the equivalent on doubles. A double calculation will take more cycles to complete, but that doesn't matter. We're dominated by instruction throughput, not latency. So the overall run-time will be longer.
In terms of further optimization, you could move the +1 outside the inner loop, by calculating right = powers[x] + powers[y] - 1. But it's possible the optimizer has already spotted that.
Your biggest "bonus" optimization will be to replace the z loop with a calculation like:
z = Math.round(Math.pow(left - 1, 1./3));
and check if z > y && left == powers[(int)z] + 1.
Other improvements if you wanted to find all triples within your limits:
start x at 2 instead of 1
replace z = Z_MAX; with break; to exit the loop early
compute X_MAX as Math.pow((powers[Z_MAX] + 1)/2, 1./3) ~= Z_MAX * Math.pow(0.5, 1./3) since if x is bigger than that, z will exceed Z_MAX
recompute Y_MAX for each x as Math.pow(powers[Z_MAX] - powers[x] + 1, 1./3)/2
BTW, a more common way to order the triples would be using z as the primary sort key, which may result in a different first 18 than you get ordering by x first. To change that, you'd make your outer loop iterate over z, which would be simpler anyway:
for (z = 1; z < Z_MAX; z++) {
for (y = 1; y < z - 1; y++) {
zy = powers[z] - 1 - powers[y];
x = Math.round(Math.pow(zy, 1./3));
if (x < y && zy == powers[(int)x])
...report triple found;
}
}

Categories

Resources