Is there a reason for the unusual behavior of floor(x), ceiling(x), etc., when x is a float type?
I mean the fact that they return another float, not an integer. Unless you explicitly specify Int as the result type.
In mathematics, engineering, etc., these functions are well-known, and defined as producing integers. One therefore has a strong expectation that that’s how they would behave in Julia.
(This unusual behavior caused a bug that cost me a few hours.)
These functions do produce an integer. They just store the integer in a floating-point type by default. Floating-point integers are still integers.
This behavior is pretty universal in programming languages (it is true in C/C++, Python, Go, …), because floating-point values have a much wider range than (hardware) integers. e.g. what result would you want floor(1e100) to give?
Yes, I realize that “floating-point integers” are integers, in the same sense that 5 is a real number. But thanks for the floor(1e100) example, that’s convincing!
Maybe it is also useful to point out floor(value) is much faster than floor(Int, value). Essentially, it is free (measured on intel i7). This could be important for hot loops! Details:
julia> using BenchmarkTools
julia> v = rand(1000000);
julia> f1(v) = ( s = 0.0 ; for value in v s+=floor(value) ; end ; s )
f1 (generic function with 1 method)
julia> f2(v) = ( s = 0 ; for value in v s+=floor(Int,value) ; end ; s )
f2 (generic function with 1 method)
julia> f3(v) = ( s = 0.0 ; for value in v s+=value ; end ; s )
f3 (generic function with 1 method)
julia> f1(v), f2(v), f3(v) # run once for good luck
(0.0, 0, 500335.41928945674)
julia> @btime f1($v) # round to Float
1.040 ms (0 allocations: 0 bytes)
0.0
julia> @btime f2($v) # round to Int
2.368 ms (0 allocations: 0 bytes)
0
julia> @btime f3($v) # do no rounding
1.037 ms (0 allocations: 0 bytes)
500335.41928945674
Rough calculation:
Extra-time for Float rounding: 1.040ms - 1.037ms ~ 3ns (free)
Extra-time for Int rounding: 2.368ms - 1.037ms ~ 1331ns (400X)