I'll start by defining the next two helper functions and then use them to get the values. These methods are your definitions of the B cases.
int nextInt(int min, int max) {
return Math.floor(Math.random() * (max - min)) + min;
}
float nextFloat(float min, float max) {
return Math.random() * (max - min) + min;
}
Then for integers
- A: return nextInt(min+1, max);
- B: return nextInt(min, max);
- C: return nextInt(min+1, max+1);
- D: return nextInt(min, max+1);
Floats are a bit more complex case. Some might argue that there isn't much difference whether the end points are included or not - especially an open ended solution could be used instead of closed - since the end points get rarely selected. But since it is perfectly possible to implement all the scenarios, I think there is mathematical interest in how it can be done.
A: In this case we can simple make sure that the illegal value is rolled again:
float f;
do {
f = nextFloat(min, max);
} while (f == min);
return f;
B:
return nextFloat(min, max);
C: Here we just switch the endpoint
float f = nextFloat(min, max);
if (f == min) {
return max;
}
return f;
D: This is the most complex scenario of all, but can be achieved as follows:
float f = nextFloat(min, max);
if (f == min) {
return max;
}
return nextFloat(min, max);
The cases A and D are a bit dirty in the sense that they may require generating more than one random number, which may be an issue in some specific scenarios. Solving this would require digging deep into the specification of the floating point to find alternative implementations. Further it should be noted that in case D the propability of max-value has very slightly higher propability than any other number, if the referenced function is completely uniform (usually not), but usually this is only a theoretical matter. (To be precise, if there are n possible values within the range, the propability of max value pmax = 1/(n-1) and the propability of any other value is (1-pmax)/(n-1)).
A little problem that should be taken care of in precise implementations of floating point case A, should be noticed. There is a possibility that the caller of the function will call it with adjacent floating points. This is not easy to see by any dummy check of the parameters, so to be safe there should be a limit on how many times the loop may be executed.