If your bounds are completely arbitrary (unlike the example you have posted), then your idiom is almost as fast as you can get. You should just eliminate the redundant lower bound checks. First ensure that the result is positive and after that just test the upper bounds. If you use the ternary operator, and with proper formatting, you can get very concise and readable code:
if (d < 0) throw new IllegalArgumentException("Argument was negative");
if (d > UPPER_LIMIT) throw new IllegalArgumentException("Argument too large");
return d < THRESHOLD_0? 0
: d < THRESHOLD_1? 1
: d < THRESHOLD_2? 2
: d < THRESHOLD_3? 3
: 4;
If your bounds, however, are as regular as you have presented them in the example, and are not going to change, then it would of course pay off to exploit that regularity, for example
if (d < 0) throw new IllegalArgumentException("Argument was negative");
if (d > UPPER_LIMIT) throw new IllegalArgumentException("Argument too large");
return (int) (d / 5);
switchon adouble?