Algorithm for calculating a decreasing value approaching a limit
I'm trying to find a Javascript version of a convenience method that I used (didn't write) a while ago in LPC, it was called dimval () and it took the following form:
NAME
dimval() - returns values with a reduced increase in output
as input values grow larger.
SYNOPSIS
float dimval(float input, float max_input, float max_output,
float min_input, float min_output, float rate);
DESCRIPTION
Returns (as a float) a value between min_output and max_output,
with values increasing at a reduced rate as they move from
min_input toward max_output.
Input is the input value.
Max_input is the maximum acceptable input. Any higher input
value will be capped to this.
Max_output is the maximum value returned.
Min_input is the (optional) minimum input. Default is zero.
Min_output is the (optional) minimum output. Default is zero.
Rate determines how quickly the cost increases to achieve
greater return values. Higher numbers are faster, lower numbers
are slower.
I read this article , but it doesn't seem to capture what I want (it looks a lot easier to start with). I also read this SO question and ... well, I think it might work ... but honestly, the math is beyond me. I understand the description above and how the parameters work together to get the desired result.
I would really appreciate it if someone could provide a method that has the above limitations in Javascript.
Hooray!
EDIT: Selecting the output from the original method.
- eval return dimval (5.0, 100.0, 100.0, 0.0, 0.0, 1.0) => 22.360680
- eval return dimval (10.0, 100.0, 100.0, 0.0, 0.0, 1.0) => 31.622776
-
eval return dimval (50.0, 100.0, 100.0, 0.0, 0.0, 1.0) => 70.710678
-
eval return dimval (10.0, 100.0, 100.0, 0.0, 0.0, 2.0) => 15.811388
-
eval return dimval (10.0, 100.0, 100.0, 0.0, 0.0, 10.0) => 3.162278
-
eval return dimval (200.0, 100.0, 100.0, 0.0, 0.0, 10.0) => 10.000000
-
eval return dimval (200.0, 100.0, 100.0, 0.0, 0.0, 1.0) => 100.000000
-
eval return dimval (1.0, 100.0, 100.0, 10.0, 0.0, 10.0) => 0.000000
Let me know if you would like me to have more samples.
source to share
Maybe something like this?
function dimval(n, min_in, max_in, min_out, max_out, exponent) {
// unscale input
n -= min_in
n /= max_in - min_in
n = Math.pow(n, exponent)
// scale output
n *= max_out - min_out
n += min_out
return n
}
0 < exponent < 1
for a quick increase first, then a smaller increase, exponent > 1
for the opposite.
Example:
> dimval(0, 0, 1, 0, 100, 2)
0
> dimval(0.1, 0, 1, 0, 100, 2)
1.0000000000000002
> dimval(0.2, 0, 1, 0, 100, 2)
4.000000000000001
> dimval(0, 0, 1, 0, 100, 0.5)
0
> dimval(0.1, 0, 1, 0, 100, 0.5)
31.622776601683793
> dimval(0.2, 0, 1, 0, 100, 0.5)
44.721359549995796
> dimval(0.3, 0, 1, 0, 100, 0.5)
54.77225575051661
> dimval(0.4, 0, 1, 0, 100, 0.5)
63.245553203367585
> dimval(0.5, 0, 1, 0, 100, 0.5)
70.71067811865476
> dimval(0.6, 0, 1, 0, 100, 0.5)
77.45966692414834
> dimval(0.7, 0, 1, 0, 100, 0.5)
83.66600265340756
> dimval(0.8, 0, 1, 0, 100, 0.5)
89.44271909999159
> dimval(0.9, 0, 1, 0, 100, 0.5)
94.86832980505137
> dimval(1, 0, 1, 0, 100, 0.5)
100
source to share
Functions:
function dimval( input, max_in, max_out, min_in, min_out, rate) {
if (rate < 0.000001) {rate = 0.000001}
if (input > max_in) {input = max_in}
if (input < min_in) {input = min_in}
mult = (max_out - min_out);
input = (input - min_in) / (max_in - min_in);
input = Math.sqrt(input) / rate;
input = (input * mult) + min_out;
if (input > max_out) {input = max_out}
return input;
}
Test:
dim1 = 'dimval(5.0, 100.0, 100.0, 0.0, 0.0, 1.0)';
dim2 = 'dimval(10.0, 100.0, 100.0, 0.0, 0.0, 1.0)';
dim3 = 'dimval(50.0, 100.0, 100.0, 0.0, 0.0, 1.0)';
dim4 = 'dimval(10.0, 100.0, 100.0, 0.0, 0.0, 2.0)';
dim5 = 'dimval(10.0, 100.0, 100.0, 0.0, 0.0, 10.0)';
dim6 = 'dimval(200.0, 100.0, 100.0, 0.0, 0.0, 10.0)';
dim7 = 'dimval(200.0, 100.0, 100.0, 0.0, 0.0, 1.0)';
dim8 = 'dimval(1.0, 100.0, 100.0, 10.0, 0.0, 10.0)';
console.log(dim1 + ' => ' + eval(dim1).toFixed(6));
console.log(dim2 + ' => ' + eval(dim2).toFixed(6));
console.log(dim3 + ' => ' + eval(dim3).toFixed(6));
console.log(dim4 + ' => ' + eval(dim4).toFixed(6));
console.log(dim5 + ' => ' + eval(dim5).toFixed(6));
console.log(dim6 + ' => ' + eval(dim6).toFixed(6));
console.log(dim7 + ' => ' + eval(dim7).toFixed(6));
console.log(dim8 + ' => ' + eval(dim8).toFixed(6));
Results:
dimval(5.0, 100.0, 100.0, 0.0, 0.0, 1.0) => 22.360680
dimval(10.0, 100.0, 100.0, 0.0, 0.0, 1.0) => 31.622777
dimval(50.0, 100.0, 100.0, 0.0, 0.0, 1.0) => 70.710678
dimval(10.0, 100.0, 100.0, 0.0, 0.0, 2.0) => 15.811388
dimval(10.0, 100.0, 100.0, 0.0, 0.0, 10.0) => 3.162278
dimval(200.0, 100.0, 100.0, 0.0, 0.0, 10.0) => 10.000000
dimval(200.0, 100.0, 100.0, 0.0, 0.0, 1.0) => 100.000000
dimval(1.0, 100.0, 100.0, 10.0, 0.0, 10.0) => 0.000000
source to share