As others have pointed out, it's in the IEEE specification, etc. Floats and doubles support NaN and Infinity, which integers do not.
In terms of the reasoning behind it, nothing is divisible by zero, and with integers you know that you are trying to divide by zero.
Floating point numbers are not exact. 0.003f - 0.001f - 0.002f is mathematically zero, but by the IEEE specification and our ability to represent numbers in computers, it's -2.3283064E-10. There's a finite number of decimal numbers you can represent in binary, and there isn't any representation that would allow us to always get a correct value for zero.
If tinyFloat == (0.003f - 0.001f - 0.002f) == -2.3283064E-10
That's mathematically zero and is practically zero, but 1f/tinyFloat == -4.2949673E9
// This still works too:
scala> Integer.MAX_VALUE / (tinyFloat * tinyFloat * tinyFloat)
res58: Float = -1.7014118E38
// But eventually you overflow
scala> Integer.MAX_VALUE / (tinyFloat * tinyFloat * tinyFloat * tinyFloat)
res59: Float = Infinity
(If you're not familiar, Scala is a JVM language, so the above value types are the same as Java.)
That last tinyFloat ^ 4 still isn't exactly zero, so it doesn't make sense for the computer to throw an ArithmeticException. This problem doesn't exist with integers. There's no other way to overflow with division. Integer.MAX_VALUE/1 is still Integer.MAX_VALUE. You either divided by zero, which is mathematically invalid and representable in binary, or you didn't, and got a valid result.