function IsBetween, or equivalent ?

Greetings,

I currently wonder if there is any existing function that requires three arguments (min, max, value), and returns true or false whether value is between min and max, or not ?

Of course, the function is pretty easy to write

function IsBetween (min : float, max : float, value : float) {
	if (min <= value  value <= max)
		return true;
	else
		return false;
}

but if it already exists, well, writing the function is useless.

Try Mathf.Clamp().

A nice function to block a value between two limits, but not to detect whether the value was outside the limits :wink:

that’s not what was asked for. i don’t know about a function that does what you are looking for, but why are you even looking for a function that you have already written?

Actually, it does exactly what he was asking for:

var n = 5; 
if (n == Mathf.Clamp(n, 1, 10)) 
    Debug.Log(n + " is between 1 and 10");

Five minutes to think about how to answer, but I guess tonyd got us beautifully. :smile:

The reason ? Simply curiosity (strangely, I don’t even remember why I asked this question, but well, this knowledge will be useful later, so it is not unworthy) ! :wink:

If it makes you feel any better, I also wrote my own “Between” function before I figured out you could accomplish the same thing with Clamp.

Generally, I think it’s best to use the built in functions where possible because I assume they are more efficient.

I’d guess that the performance variation of n==Clamp, a Between utility function and inlined greater/lessthan tests would be trivial. But one doesn’t have to guess - write loops that do each over 10,000 or 100,000 iterations and time them.

But in normal use, its not going to make any difference. So use whichever one is most readable.

p.s. - I just did such a test. At 100,000 iterations, the Clamp and Between methods are pretty much the same (about 2.4ms) and the inlined greater/less than is a little bit faster at about 2.1ms. Doesn’t seem worth worrying about.

Might be different in java.

Here’s the test code (C#)

private static bool Between(float v, float min, float max)
{
    return v > min  v < max;
}

void testLoops()
{
    System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();

    timer.Reset();
    timer.Start();
    for (int i = 0; i < 100000; i++)
    {
        float v = Random.value;
        bool test = Between(v, 1, 100);
    }        
    double betweenTime = timer.Elapsed.TotalMilliseconds;

    timer.Reset();
    timer.Start();
    for (int i = 0; i < 100000; i++)
    {
        float v = Random.value;
        bool test = v == Mathf.Clamp(v, 1, 100);
    }
    double clampTime = timer.Elapsed.TotalMilliseconds;

    timer.Reset();
    timer.Start();
    for (int i = 0; i < 100000; i++)
    {
        float v = Random.value;
        bool test = v > 1  v < 100;
    }
    double inlineTime = timer.Elapsed.TotalMilliseconds;

    print(string.Format("Between: {0}", betweenTime));
    print(string.Format("Clamp: {0}", clampTime));
    print(string.Format("Inline: {0}", inlineTime));
}
function IsBetween (value : float, min : float, max : float)
{
	return min < value  value < max;
}

var betweenTimeStart : double;
var betweenTimeEnd : double;
var betweenDuration : double;

var clampTimeStart : double;
var clampTimeEnd : double;
var clampDuration : double;

var inlineTimeStart : double;
var inlineTimeEnd : double;
var inlineDuration : double;

var i : int;
var v : float;
var test : boolean;

betweenTimeStart = Time.time;
for (i = 0; i < 100000; i++)
{
	v = Random.value;
	test  = IsBetween (v, 1, 100);
}
betweenTimeEnd = Time.time;
betweenDuration = betweenTimeEnd - betweenTimeStart;

clampTimeStart = Time.time;
for (i = 0; i < 100000; i++)
{
	v = Random.value;
	test = v == Mathf.Clamp (v, 1, 100);
}
clampTimeEnd = Time.time;
clampDuration = clampTimeEnd - clampTimeStart;

inlineTimeStart = Time.time;
for (i = 0; i < 100000; i++)
{
	v = Random.value;
	test = 1 < v  v < 100;
}
inlineTimeEnd = Time.time;
inlineDuration = inlineTimeEnd - inlineTimeStart;

print ("betweenDuration=" + betweenDuration);
print ("clampDuration=" + clampDuration);
print ("inlineDuration=" + inlineDuration);

Values : 0, 0, 0.

Did I do a mistake ?

Its possible that Time.time doesn’t have adequate resolution for this task. You could try increasing the iteration count to 1,000,000. Its also possible that its not asynchronous and so it only updates sometimes and never changes during your test function. That would be easy to detect by comparing its value at the start to its value at the end.

Reasons like that are why I used the Stopwatch - it wraps the Windows high performance timer API functions (though the details of Mono’s linkages are a mystery to me - it worked is all I know) and has resolution in the millionths of a second on most machines. Is there nothing like that for Java?

Unless you are going to be doing this in loops that actually iterate thousands of times per frame, I wouldn’t worry about it at all. If an “IsBetween” function makes your code easier to read, then use that. Or inline the comparisons if you prefer. Or use Clamp.

If you start getting performance problems, then profile the whole system and find where your cycles are burning and optimize there.

Don’t ever assume anything. :wink: Sometimes they are not, like the various Lerp functions…it’s faster to write your own functions. (See here.) In this case, the Clamp function is in fact the slowest method…not by a lot, but it is. It’s also awkward compared to a specific Between function.

Yes, you can’t use Time.time like this, since it doesn’t update during the same frame (only between frames). Use Time.realtimeSinceStartup instead.

–Eric

Well, I wrote my own Lerp functions for different reasons… I needed constant linear movement with no deceleration. I wasn’t getting that with Vector3.Lerp.

But Vector3.Lerp is constantly linear and has no deceleration.

–Eric

betweenDuration=0,00439215451478958
clampDuration=0,00410838052630424
inlineDuration=0,0035258587449789

C# faster ? Hmmm.

Try looping more times; I’m not sure about the accuracy when it’s that fast. With longer loops, I get:

betweenDuration=0.192223012447357
clampDuration=0.213572978973389
inlineDuration=0.13409298658371

–Eric

Maybe I was using it wrong. That’s what I get for following the script reference! :lol:

If you’re referring to the “// Follows the target position like with a spring” example, see here.

–Eric