I have trouble figuring out why a simple division like this one always returns 0.
System.out.println(4091365376L / 4091495462L * 100L);
I suffixed all numbers with Ls so they're treated as Longs. I keep getting a zero.
I'm trying to calculate the percentage of 4091365376L to 4091495462L. My values are Longs but I'm just looking for a simple Integer value.
You are a victim of integer rounding (actually: truncation). Try this:
System.out.println(4091365376L * 100L / 4091495462L);
Prints 99. Or cast to double implicitly:
System.out.println(100.0 * 4091365376L / 4091495462L);
Giving 99.99682057572328. Your problem is that 4091495462L is slightly bigger than 4091365376L so when diving them, the result is truncated to 0 (try 3 / 4, if you are not convinced). and 0 times 100 is...
4091365376L / 4091495462L * 100L
\_______________________/ |
0.99... = 0 |
\_________________________/
0
You could express it like
100 * 4091365376L / 4091495462L
then it would become
100 * 4091365376L / 4091495462L
\_______________/ |
409136537600L |
\____________________________/
99.99... = 99
Order is important, as is type. The output of a long divided by a long is a long. The result of the division you're performing is 0, and 0 * 100 == 0. You would be much better off using something like this:
System.out.println((long) (4091365376.0 / 4091495462.0 * 100));
In integer math:
4091365376 / 4091495462 = 0
0 * 100 = 0
You're expecting
4091365376 / 4091495462 = 0.9999682057572327
0.9999682057572327 * 100 = 99.99682057572327
but you can't do that with integers (or long integers). Use doubles if you want a double value.
Related
I want to know why is that code times perimeter 100 then divide it by 100?
(double)Math.round(dblPerimeter * 100) / 100);
This code would round dblPerimeter to 2 decimal places.
Example on how this works:
Let dblPerimeter = 123.456. Round dblPerimeter to 2 decimals
multiply by 100: 123.456 * 100 = 12345.6
Math.round() 12345.6 to 12346
cast 12346 to (double): 12346.0
divide by 100: 12346.0 / 100 = 123.46
Rounding to the second decimal place. Eventhough you can never be exactly sure with floating-point-arithmetics, but this is what it is supposed to do.
I want to get the number of micro seconds in a day
so I tried as per below
long microDay = 24 * 60 * 60 * 1000 * 1000;
for which I am expecting value as 86400000000 but when I print it
System.out.println(microDay);
The value is 500654080
After spending 3 hours and breaking my head to know the reason,final I found that java think 24,60 and 1000 as int values and int*int =int but the maximum value of int is 2147483647 so it cant store 86400000000 and hence it the output is 500654080 (but I am not sure)
In the second case I wanted to calculate miliseconds in a day and the formula goes like this
long miliDay = 24 * 60 * 60 * 1000;
System.out.println(miliDay );
output 86400000
now when I did
System.out.println(microDay/ miliDay);
output 5
but when I tried this in a calculator 500654080/86400000= 5.794607407407407
why there is different in result?
You're performing 32-bit integer arithmetic, as every operand in 24 * 60 * 60 * 1000 * 1000 is an int... but the result is bigger than Integer.MAX_VALUE, so it's overflowing (just as you suspected). (This is actually happening at compile-time in this case, because it's a compile-time constant, but the effect is the same as if it happened at execution time.)
Effectively, each operation is truncated to 32 bits. As it happens, only the final multiplication by 1000 takes the result over 231 - 86400000 is fine.
86400000000 in binary is:
1010000011101110101110110000000000000
^
\- Bit 33
So after overflow, we just chop any leading bits until we've got 32:
00011101110101110110000000000000
And that value is 500654080.
Just use long instead, e.g.
long microDay = 24L * 60L * 60L * 1000L * 1000L;
(You definitely don't need all those constants to be of type long, but being consistent means it's obvious that all the operations will be performed using 64-bit arithmetic, with no need to consider associativity etc.)
A better approach, however, would be to use TimeUnit:
long microDay = TimeUnit.DAYS.toMicroseconds(1);
As for the division part, you're performing integer division - so the result is the integer part, rounded towards 0. If you want floating point arithmetic, you need to cast one of the operands to float or double... although if you start off with the right values, of course, you should get an exact integer anyway (1000).
For the first part, put a "L" at the end of one (or more) of the constants and Java will then use long arithmetic. e.g.
long microDay = 24L * 60 * 60 * 1000 * 1000;
Addendum: Why did you get 500654080?
86400000000 decimal = 141DD76000 hex.
But, the integer only holds 32 bits, which is 8 "digits". So you lose the leading 14 and retain 1DD76000 hex.
Converting that to decimal gives 500654080.
As for the division, when you divide ints by ints (or longs by longs) Java returns the result as an int or long, so it has to truncate (or round, but Java chose to truncate) the result to 5 instead of 5.7946... Force it to do floating point arithmetic by casting one of the values to a double, e.g.
System.out.println((double)microDay/ miliDay);
When you are performing a division between 2 integers, the results are an integer. The results of the arithmetic operation will be rounded down to the nearest integer.
int i = 5 / 2; // 2.5 is rounded down to 2
if you want the output to include the decimal precision, you will need to use a different primitive data type and explicitly specify your operands to be doubles.
double j = 5 / 2; //2.0 as 5 / 2 yields and integer 2 which will be casted to a double
double j = 5 / 2.0; //2.5 explicit usage of a double will tell the compiler to return the results in double
The nuclear operations inside
long microDay = 24 * 60 * 60 * 1000 * 1000;
are all Integers specific. Max value of Integer object is 2147483647. Which exceeds the original output which is long.
Simply specifying long to variable doesn't mean all operations using [ * ] will be done using long instances. All operations done in assignment became sort of truncated.
Solution is to explicitly specify that all nuclear operations should happen over long instance and not int instances.
long microDay = 24L * 60L * 60L * 1000L * 1000L;
I would like to check if the result is measurable; that is, whether it has a finite number if decimal places. What do i mean?
double x = 5.0 / 9.0; // x = 0.(5)
x is not measurable.
I want to round x to the second digit ( x = 0.56 ), but in such case:
double x = 1.0 / 8.0; // x = 0.125
I don't want to round anything.
So here is my question. How do i decide if the result can be measured or not?
You cannot. That is the reason, why 1.0 / 3 / 100 * 3 * 100 gives you 0.9999...9. You only have so many bits to represent the numbers. You cannot distinguish between the period
1.0 / 3 and a number that actually has 0.3333.....3 as value
The only fractions which will be exactly represented in a binary will be ones where the denominator is a power of two. If your input is two integers for the numerator and denominator then find the prime factorisation of both and remove the common factors. Then check the only remaining factors on the denominator are power of 2. Say if we want to find 56 / 70 this is 2^3 * 7 / ( 2 * 5 * 7) removing common factors gives 2^2 / 5 so that will not work. But 63 / 72 = (7*3^2) / (2^3 * 3^2) = 7 / 2^3 so will be a terminating binary number
If your working in decimal then powers of 2 and 5 on the denominator will be allowed.
So I've written a programme used to solve a concrete equation having been given one parameter int n. The code I have is:
static double getSolution1(int n)
{
double [] a = new double[n+1];
a[0] =-1;
for (int i = 1; i < n+1; i++)
{
a[i] = a[i-1] * ( ( 2 / ( 3 * n ) ) * Math.cos(2 * a[i-1]) );
}
return a[n];
}
As far as I can tell, the code works fine and should be filling in the various parts of the array. But that's not happening, apart from a[0] = -1 that I have told the programme, it is treating all other entries as 0 as though it has not undergone the loop. Using a debug, that's the only problem I can really find. How can I fix that?
2 / 3 *n would give you zero, use all floats or doubles like 2.0f 3.0f
The "2 / ( 3 * n )" is being evaluated as int; and it works out as 0.
To fix, change it to "2.0 / (3.0 * n)"
As Pulkit said, 2/3 *n yields zero. Why?
Integer division will always round down your result to the nearest whole number. So:
2 / 3 = .666
floor(.666) = 0
To prevent this, you can add f to the end of 2 or 3. That'll cause the operation to evaluate as a float rather than an integer, avoiding the rounding.
2f / 3f
You can also add d to 2 or 3. That'll cause the operation to evaluate as a double rather than an integer.
2d / 3d
the expression ( 2 / ( 3 * n ) return an integer type. so for every number between 1 and 0, int type will be 0. what you can do is to let compiler treats 2 and 3 as float type or double type. you can use 2.0 instead of 2. or 3.0 instead of 3
I'm currently coding a little download manager and I get a funny output when I try to calculate the download-progress in percent. This is what i use to calculate it:
int progress = (byte_counter * 100) / size;
System.out.println("("+byte_counter+" * 100) = "+(byte_counter * 100)
+" / "+size+" = "+progress);
byte-counter is an int (it counts the total bytes read from the InputStream) and size is the length of the downloaded file in bytes.
This works great with small downloads. But when i get to bigger files (40MB) it starts making funny things. The Output for the calculation looks like this:
[...]
(21473280 * 100) = 2147328000 / 47659008 = 45
(21474720 * 100) = 2147472000 / 47659008 = 45
(21476160 * 100) = -2147351296 / 47659008 = -45
(21477600 * 100) = -2147207296 / 47659008 = -45
[...]
I don't know why, but the calculation gets negative. Since an normal Integer should be fine with numbers till 231-1, this shouldn't be the problems root. But what am I missing?
See http://en.wikipedia.org/wiki/Arithmetic_overflow
To fix in java, try using a long instead.
int progress = (int) ((byte_counter * 100L) / size);
or reverse order of operations
int progress = (int) (((float) byte_counter) / size) * 100);
21476160 * 100 = 2 147 616 000 is greater than 2 147 483 647, the max int.
You're overflowing.
Use long for your calculations.
2^31-1 = 2147483647 < 21476160 * 100 = 2147616000
You should use a long -- 2147760000 in binary is 10000000 00000100 00110111 10000000 and since the most significant bit is 1 it is interpreted as a negative number.