java - Why does Math.floor return a double? - Stack Overflow
java - calculate Math floor - Stack Overflow
Why floor, round and ceil return double?
java - (int) Math.sqrt(n) much slower than (int) Math.floor(Math.sqrt(n)) - Stack Overflow
What is the Math floor (-4.7) in Java?
What is Math.floor JavaScript?
How to apply floor in Java?
Videos
According to the same Javadoc:
If the argument is NaN or an infinity or positive zero or negative zero, then the result is the same as the argument. Can't do that with an int.
The largest double value is also larger than the largest int, so it would have to be a long.
It's for precision. The double data-type has a 53 bit mantissa. Among other things that means that a double can represent all whole up to 2^53 without precision loss.
If you store such a large number in an integer you will get an overflow. Integers only have 32 bits.
Returning the integer as a double is the right thing to do here because it offers a much wider usefull number-range than a integer could.
Might be stupid question, but this has always puzzled me about Java.
Why functions Math.floor(), Math.round() and Math.ceil() return double value?
I thought main point of those is to convert floating point number into whole number. So why not returning long or int? That way we don't have to manually cast everytime.
The Math.floor method just delegates the call to the StrictMath.floor method (as seen on java.lang.StrictMath's source code). This method is a native method. After this method the cast does not have to do anything because it is already a number that is equal to an integer (so no decimal places).
Maybe the native implementation of floor is faster than the cast of a double value to an int value.
I cannot reproduce the same results. Using this simple Java code below, the function without the call to Math.floor is consistently faster:
with floor elapsed milliseconds: 7354
without floor elapsed milliseconds: 4252
public class TestCast {
private static final int REPS = Integer.MAX_VALUE / 4;
private static void withFloor() {
long sum = 0;
long start = System.currentTimeMillis();
for (int i = REPS; i != 0; --i) {
sum += (int)Math.floor(Math.sqrt(i));
}
long end = System.currentTimeMillis();
long elapsed = end - start;
System.out.println("with floor elapsed milliseconds: " + elapsed);
System.out.println(sum);
}
private static void withoutFloor() {
long sum = 0;
long start = System.currentTimeMillis();
for (int i = REPS; i != 0; --i) {
sum += (int)Math.sqrt(i);
}
long end = System.currentTimeMillis();
long elapsed = end - start;
System.out.println("without floor elapsed milliseconds: " + elapsed);
System.out.println(sum);
}
public static void main(String[] args) {
withFloor();
withoutFloor();
}
}
Also, looking at the disassembled byte code we can clearly see the call to Math.floor in the first function and no call in the second. There must be something else going on in your code. Perhaps you can post your code or a shortened version of it that shows the results that you are seeing.
private static void withFloor();
Code:
0: lconst_0
1: lstore_0
2: invokestatic #2 // Method java/lang/System.currentTimeMillis:()J
5: lstore_2
6: ldc #3 // int 536870911
8: istore 4
10: iload 4
12: ifeq 35
15: lload_0
16: iload 4
18: i2d
19: invokestatic #4 // Method java/lang/Math.sqrt:(D)D
22: invokestatic #5 // Method java/lang/Math.floor:(D)D
25: d2i
26: i2l
27: ladd
28: lstore_0
29: iinc 4, -1
32: goto 10
35: invokestatic #2 // Method java/lang/System.currentTimeMillis:()J
38: lstore 4
40: lload 4
42: lload_2
43: lsub
44: lstore 6
46: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
49: new #7 // class java/lang/StringBuilder
52: dup
53: invokespecial #8 // Method java/lang/StringBuilder."<init>":()V
56: ldc #9 // String with floor elapsed milliseconds:
58: invokevirtual #10 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
61: lload 6
63: invokevirtual #11 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
66: invokevirtual #12 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
69: invokevirtual #13 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
72: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
75: lload_0
76: invokevirtual #14 // Method java/io/PrintStream.println:(J)V
79: return
private static void withoutFloor();
Code:
0: lconst_0
1: lstore_0
2: invokestatic #2 // Method java/lang/System.currentTimeMillis:()J
5: lstore_2
6: ldc #3 // int 536870911
8: istore 4
10: iload 4
12: ifeq 32
15: lload_0
16: iload 4
18: i2d
19: invokestatic #4 // Method java/lang/Math.sqrt:(D)D
22: d2i
23: i2l
24: ladd
25: lstore_0
26: iinc 4, -1
29: goto 10
32: invokestatic #2 // Method java/lang/System.currentTimeMillis:()J
35: lstore 4
37: lload 4
39: lload_2
40: lsub
41: lstore 6
43: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
46: new #7 // class java/lang/StringBuilder
49: dup
50: invokespecial #8 // Method java/lang/StringBuilder."<init>":()V
53: ldc #15 // String without floor elapsed milliseconds:
55: invokevirtual #10 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
58: lload 6
60: invokevirtual #11 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
63: invokevirtual #12 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
66: invokevirtual #13 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
69: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
72: lload_0
73: invokevirtual #14 // Method java/io/PrintStream.println:(J)V
76: return
Personally, I would write the code just as:
unsigned int x
unsigned int y
public void myFunction()
{
getTile(x / 64, y / 64).doOperation();
}
since being a tilemap, you can use it (and thus assume) using positive-only values. This does not affect readability because x and y are declared as unsigned int, quite close to the block, and every programmer knows whether the language performs or not an integer division with the / operator when it is applied to two integers (most of them do). In fact, such a geometrical scenario is probably one of the few ones that shows that integer divisions can be useful.
Moreover, thinking about omptimization of such a snippet represents, in my opinion, one of those cases of "unnecessary preventive optimization": you can often assume that such operations will not be a bottleneck of your code, and thus take actions only when profiling shows the opposite. Performance of casting operations can be difficult to evaluate, in general: they largely depend not only on the language, but also on the compiler, which can remove unnecessary casts, or "translate" them in worse/better assembler.
I guess it safe to assume it is never negative, given that doing so would be reading outside the confine of the array. If that the case, simply rotate the bits 6 times which gives the same results but is far faster than using the int divide counterpart.
int x
int y
public void myFunction()
{
getTile(x >> 6, y >> 6).doOperation();
}