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.

+3


source to share


3 answers


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

      

+1


source


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

      

+1


source


I just went through an exercise to create something like this and came up with:

z * (max - max -x )

Where z is the initial value, max is the asymptote, and x is the variable value.

+1


source







All Articles