I wrote a javascript version of Lagrange algorithm, but it kept going wrong when I run it, I don't know what went wrong.
I use this to calculate time.
When I pass a cSeconds as a variable, sometimes it returns a minus value which is obviously wrong...
function LagrangeForCat(cSeconds){
var y = [2592000,7776000,15552000,31104000,93312000,155520000,279936000,404352000,528768000,622080000,715392000,870912000,995328000,1119744000,1244160000,1368576000,1492992000,1617408000,1741824000,1866240000,1990656000,2115072000,2239488000,2363904000,2488320000,2612736000,2737152000,2861568000,2985984000,3110400000,3234816000,3359232000,3483648000,3608064000];
var x = [604800,1209600,1814400,2592000,5184000,7776000,15552000,23328000,31104000,46656000,62208000,93312000,124416000,155520000,186624000,217728000,248832000,279936000,311040000,342144000,373248000,404352000,435456000,466560000,497664000,528768000,559872000,590976000,622080000,653184000,684288000,715392000,746496000,777600000];
var l = 0.0;
for (var j = 0; j < 34; j++) {
var s = 1.0;
for (var i = 0; i < 34; i++) {
if (i != j)
s = s * ((cSeconds - x[i]) / (x[j] - x[i]));
}
l = l + s * y[j];
}
var result = l / (24 * 60 * 60);
var Days = Math.floor(result);
//get float seconds data
var littleData = String(result).split(".")[1];
var floatData = parseFloat("0."+littleData);
var second = floatData *60*60*24;
var hours = Math.floor(second/(60*60));
var minutes = Math.floor(second % 3600/60);
var seconds = Math.floor(second % 3600) % 60;
var returnData = {days:Days,hours: hours + ':' + minutes + ':' + seconds}
return returnData;
}
I don't believe the issue is with your code but with the data set.
I tried a few things, for instance if you have cSeconds = one of the x values, then you get the correct result (I could check that it was equal to the matching y value).
I put all the data in open office and drew the graph it was like the square root function but more extreme (the 'straight' part look very straight) then I remembered that when you interpolate you usually get a polynomial that crosses the points you want but can be very wild outside between the point.
To test my theory I modified the algorithm to control at which x/y index to start and tried for all the values:
for (let i = 0; i < 35; ++i) {
LagrangeForCat(63119321, i, 34)
}
Together with a console.log inside LagrangeForCat it gives me the interpolated y value if I use all the x/y arrays (i=0), if I ignore the first x/y point (i=1), the first two (i=2), ...
00-34 -6850462776.278063
01-34 549996977.0003194
02-34 718950902.7592317
03-34 723883771.1443908
04-34 723161627.795225
05-34 721857113.1756063
06-34 721134873.0889213
07-34 720845478.4754647
08-34 720897871.7910147
09-34 721241470.2886044
10-34 722280314.1033486
11-34 750141284.0070543
12-34 750141262.289736
13-34 750141431.2562406
14-34 750141089.6980047
15-34 750141668.8768387
16-34 750142353.3267975
17-34 750141039.138794
18-34 750141836.251831
19-34 750138039.6240234
20-34 750141696.7529297
21-34 750141120.300293
22-34 750141960.4248047
23-34 750140874.0966797
24-34 750141337.5
25-34 750141237.4694824
26-34 750141289.2150879
27-34 750141282.5408936
28-34 750141284.2094421
29-34 750141283.987999
30-34 750141284.0002298
31-34 750141284.0000689
32-34 750141283.9999985
33-34 3608064000
34-34 0
Exclude 33-34 and 34-34 (there's just not enough data to interpolate).
For the example x=63119321 you'd expect y to be between 715392000 and 870912000 you can see that if you ignore the first 2-3 values the interpolation is "believable", if you ignore more values you interpolate based off the very straight part of the curve (see how consistent the interpolation is from 11-34 onward).
I use to work on a project where interpolation was needed, to avoid those pathological cases we opted for linear interpolation trading accuracy for security (and we could generate all the x/y points we wanted). In your case I'd try to use a smaller set, for instance only two values smaller than cSeconds and two greater like this:
function LagrangeForCat(cSeconds) {
var x = [...];
var y = [...];
let begin = 0,
end = 34
for (let i = 0; i < 34; ++i) {
if (cSeconds < x[i]) {
begin = (i < 3) ? 0 : i - 2
end = (i > (x.length - 1)) ? x.length : i + 1
break
}
}
let result = 0.0;
for (let i = begin; i < end; ++i) {
let term = y[i] / (24 * 60 * 60)
for (let j = begin; j < end; ++j) {
if (i != j)
term *= (cSeconds - x[j]) / (x[i] - x[j]);
}
result += term
}
var Days = Math.floor(result);
// I didn't change the rest of the function didn't even looked at it
}
If you find this answer useful please consider marking it as answered it'd be much appreciated.
It's kind of math problem. I want to fire specific number of setTimeout (the number is based on an array length) in a specific period of time (say, 5 seconds).
The first setTimeout should start at 0 sec. and the last at 5 sec.. All timeouts between should start with an ease-in effect, so that each timeout starts faster.
There's an example which ilustrates what I want to achieve exactly.
I'm struggling around this line:
next += timePeriod/3.52/(i+1);
which works almost perfect in demo example (for any timePeriod), but obviously it doesn't work for a different letters.length as I have used static number 3.52.
How do I calculate next?
var letters = [
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T'
];
var div = $('#container');
var timePeriod = 5000; // 5 seconds;
var perLetter = timePeriod/(letters.length-1); // it gives equal time between letters
var next = 0;
for(var i=0; i<letters.length; i++){
setTimeout(function(letter){
//div.append('<span class="letter">' + letter + '</span>');
// Used "|" instead of letter, For better redability:
div.append('<span class="letter">|</span>');
}, next, letters[i]);
// Can't find the logic here:
next += timePeriod/3.52/(i+1);
};
///////////////// FOR DEMO: ///////////////
var sec = timePeriod/1000;
var secondsInterval = setInterval(seconds, 1000);
var demoInterval = setInterval(function(){
sec >= 0 || clearInterval(demoInterval);
div.append('\'');
}, 30);
function seconds(){
sec || clearInterval(secondsInterval);
$('#sec').text(sec-- || 'DONE');
}
seconds();
.letter{
color : red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span id=container></span>
<span id=sec class=letter></span>
var steps = letters.length;
var target = timePeriod;
function easeOutQuad(t, b, c, d) {
t /= d;
return -c * t*(t-2) + b;
};
var arrayOfTimeouts = new Array(steps);
var n;
var prev = 0;
for(var i = 1; i <= steps; i++){
n = easeOutQuad(i, 0.0, target, steps);
arrayOfTimeouts[i-1] = n-prev;
prev = n;
}
This one should work with any input value.
fiddle
Note that the graph appears to be slightly too fast but I believe that discrepancy to be a product of timing imperfections, as the sum of my array equals the timePeriod exactly.
more on easing equations
Here's a solution based on a geometric series. It's a bit goofy but it works. It generates an array with your timeout values.
Steps = size of your array.
Target = the total time.
var steps = 50;
var target = 5000;
var fraction = 1.5 + steps / 7;
var ratio = (fraction-1) / fraction;
var n = target / fraction;
var sum = 0;
var arrayOfTimeouts = new Array(steps);
for(var i = 0; i < steps; i++){
sum += n;
arrayOfTimeouts[i] = n;
n *= ratio;
}
console.log(arrayOfTimeouts, sum);
Is it possible to get a random number between 1-100 and keep the results mainly within the 40-60 range? I mean, it will go out of that range rarely, but I want it to be mainly within that range... Is it possible with JavaScript/jQuery?
Right now I'm just using the basic Math.random() * 100 + 1.
The simplest way would be to generate two random numbers from 0-50 and add them together.
This gives a distribution biased towards 50, in the same way rolling two dice biases towards 7.
In fact, by using a larger number of "dice" (as #Falco suggests), you can make a closer approximation to a bell-curve:
function weightedRandom(max, numDice) {
let num = 0;
for (let i = 0; i < numDice; i++) {
num += Math.random() * (max/numDice);
}
return num;
}
JSFiddle: http://jsfiddle.net/797qhcza/1/
You have some good answers here that give specific solutions; let me describe for you the general solution. The problem is:
I have a source of more-or-less uniformly distributed random numbers between 0 and 1.
I wish to produce a sequence of random numbers that follow a different distribution.
The general solution to this problem is to work out the quantile function of your desired distribution, and then apply the quantile function to the output of your uniform source.
The quantile function is the inverse of the integral of your desired distribution function. The distribution function is the function where the area under a portion of the curve is equal to the probability that the randomly-chosen item will be in that portion.
I give an example of how to do so here:
http://ericlippert.com/2012/02/21/generating-random-non-uniform-data/
The code in there is in C#, but the principles apply to any language; it should be straightforward to adapt the solution to JavaScript.
Taking arrays of numbers, etc. isn't efficient. You should take a mapping which takes a random number between 0 to 100 and maps to the distribution you need. So in your case, you could take f(x)=-(1/25)x2+4x to get a distribution with the most values in the middle of your range.
I might do something like setup a "chance" for the number to be allowed to go "out of bounds". In this example, a 20% chance the number will be 1-100, otherwise, 40-60:
$(function () {
$('button').click(function () {
var outOfBoundsChance = .2;
var num = 0;
if (Math.random() <= outOfBoundsChance) {
num = getRandomInt(1, 100);
} else {
num = getRandomInt(40, 60);
}
$('#out').text(num);
});
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button>Generate</button>
<div id="out"></div>
fiddle: http://jsfiddle.net/kbv39s9w/
I needed to solve this problem a few years ago and my solution was easier than any of the other answers.
I generated 3 randoms between the bounds and averaged them. This pulls the result towards the centre but leaves it completely possible to reach the extremities.
It looks stupid but you can use rand twice:
var choice = Math.random() * 3;
var result;
if (choice < 2){
result = Math.random() * 20 + 40; //you have 2/3 chance to go there
}
else {
result = Math.random() * 100 + 1;
}
Sure it is possible. Make a random 1-100. If the number is <30 then generate number in range 1-100 if not generate in range 40-60.
There is a lot of different ways to generate such random numbers. One way to do it is to compute the sum of multiple uniformly random numbers. How many random numbers you sum and what their range is will determine how the final distribution will look.
The more numbers you sum up, the more it will be biased towards the center. Using the sum of 1 random number was already proposed in your question, but as you notice is not biased towards the center of the range. Other answers have propose using the sum of 2 random numbers or the sum of 3 random numbers.
You can get even more bias towards the center of the range by taking the sum of more random numbers. At the extreme you could take the sum of 99 random numbers which each were either 0 or 1. That would be a binomial distribution. (Binomial distributions can in some sense be seen as the discrete version of normal distributions). This can still in theory cover the full range, but it has so much bias towards the center that you should never expect to see it reach the endpoints.
This approach means you can tweak just how much bias you want.
What about using something like this:
var loops = 10;
var tries = 10;
var div = $("#results").html(random());
function random() {
var values = "";
for(var i=0; i < loops; i++) {
var numTries = tries;
do {
var num = Math.floor((Math.random() * 100) + 1);
numTries--;
}
while((num < 40 || num >60) && numTries > 1)
values += num + "<br/>";
}
return values;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="results"></div>
The way I've coded it allows you to set a couple of variables:
loops = number of results
tries = number of times the function will try to get a number between 40-60 before it stops running through the while loop
Added bonus: It uses do while!!! Awesomeness at its best
You can write a function that maps random values between [0, 1) to [1, 100] according to weight. Consider this example:
Here, the value 0.95 maps to value between [61, 100].
In fact we have .05 / .1 = 0.5, which, when mapped to [61, 100], yields 81.
Here is the function:
/*
* Function that returns a function that maps random number to value according to map of probability
*/
function createDistributionFunction(data) {
// cache data + some pre-calculations
var cache = [];
var i;
for (i = 0; i < data.length; i++) {
cache[i] = {};
cache[i].valueMin = data[i].values[0];
cache[i].valueMax = data[i].values[1];
cache[i].rangeMin = i === 0 ? 0 : cache[i - 1].rangeMax;
cache[i].rangeMax = cache[i].rangeMin + data[i].weight;
}
return function(random) {
var value;
for (i = 0; i < cache.length; i++) {
// this maps random number to the bracket and the value inside that bracket
if (cache[i].rangeMin <= random && random < cache[i].rangeMax) {
value = (random - cache[i].rangeMin) / (cache[i].rangeMax - cache[i].rangeMin);
value *= cache[i].valueMax - cache[i].valueMin + 1;
value += cache[i].valueMin;
return Math.floor(value);
}
}
};
}
/*
* Example usage
*/
var distributionFunction = createDistributionFunction([
{ weight: 0.1, values: [1, 40] },
{ weight: 0.8, values: [41, 60] },
{ weight: 0.1, values: [61, 100] }
]);
/*
* Test the example and draw results using Google charts API
*/
function testAndDrawResult() {
var counts = [];
var i;
var value;
// run the function in a loop and count the number of occurrences of each value
for (i = 0; i < 10000; i++) {
value = distributionFunction(Math.random());
counts[value] = (counts[value] || 0) + 1;
}
// convert results to datatable and display
var data = new google.visualization.DataTable();
data.addColumn("number", "Value");
data.addColumn("number", "Count");
for (value = 0; value < counts.length; value++) {
if (counts[value] !== undefined) {
data.addRow([value, counts[value]]);
}
}
var chart = new google.visualization.ColumnChart(document.getElementById("chart"));
chart.draw(data);
}
google.load("visualization", "1", { packages: ["corechart"] });
google.setOnLoadCallback(testAndDrawResult);
<script src="https://www.google.com/jsapi"></script>
<div id="chart"></div>
Here's a weighted solution at 3/4 40-60 and 1/4 outside that range.
function weighted() {
var w = 4;
// number 1 to w
var r = Math.floor(Math.random() * w) + 1;
if (r === 1) { // 1/w goes to outside 40-60
var n = Math.floor(Math.random() * 80) + 1;
if (n >= 40 && n <= 60) n += 40;
return n
}
// w-1/w goes to 40-60 range.
return Math.floor(Math.random() * 21) + 40;
}
function test() {
var counts = [];
for (var i = 0; i < 2000; i++) {
var n = weighted();
if (!counts[n]) counts[n] = 0;
counts[n] ++;
}
var output = document.getElementById('output');
var o = "";
for (var i = 1; i <= 100; i++) {
o += i + " - " + (counts[i] | 0) + "\n";
}
output.innerHTML = o;
}
test();
<pre id="output"></pre>
Ok, so I decided to add another answer because I felt like my last answer, as well as most answers here, use some sort of half-statistical way of obtaining a bell-curve type result return. The code I provide below works the same way as when you roll a dice. Therefore, it is hardest to get 1 or 99, but easiest to get 50.
var loops = 10; //Number of numbers generated
var min = 1,
max = 50;
var div = $("#results").html(random());
function random() {
var values = "";
for (var i = 0; i < loops; i++) {
var one = generate();
var two = generate();
var ans = one + two - 1;
var num = values += ans + "<br/>";
}
return values;
}
function generate() {
return Math.floor((Math.random() * (max - min + 1)) + min);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="results"></div>
I'd recommend using the beta distribution to generate a number between 0-1, then scale it up. It's quite flexible and can create many different shapes of distributions.
Here's a quick and dirty sampler:
rbeta = function(alpha, beta) {
var a = 0
for(var i = 0; i < alpha; i++)
a -= Math.log(Math.random())
var b = 0
for(var i = 0; i < beta; i++)
b -= Math.log(Math.random())
return Math.ceil(100 * a / (a+b))
}
var randNum;
// generate random number from 1-5
var freq = Math.floor(Math.random() * (6 - 1) + 1);
// focus on 40-60 if the number is odd (1,3, or 5)
// this should happen %60 of the time
if (freq % 2){
randNum = Math.floor(Math.random() * (60 - 40) + 40);
}
else {
randNum = Math.floor(Math.random() * (100 - 1) + 1);
}
The best solution targeting this very problem is the one proposed by BlueRaja - Danny Pflughoeft but I think a somewhat faster and more general solution is also worth mentioning.
When I have to generate random numbers (strings, coordinate pairs, etc.) satisfying the two requirements of
The result set is quite small. (not larger than 16K numbers)
The result set is discreet. (like integer numbers only)
I usually start by creating an array of numbers (strings, coordinate pairs, etc.) fulfilling the requirement (In your case: an array of numbers containing the more probable ones multiple times.), then choose a random item of that array. This way, you only have to call the expensive random function once per item.
Distribution
5% for [ 0,39]
90% for [40,59]
5% for [60,99]
Solution
var f = Math.random();
if (f < 0.05) return random(0,39);
else if (f < 0.95) return random(40,59);
else return random(60,99);
Generic Solution
random_choose([series(0,39),series(40,59),series(60,99)],[0.05,0.90,0.05]);
function random_choose (collections,probabilities)
{
var acc = 0.00;
var r1 = Math.random();
var r2 = Math.random();
for (var i = 0; i < probabilities.length; i++)
{
acc += probabilities[i];
if (r1 < acc)
return collections[i][Math.floor(r2*collections[i].length)];
}
return (-1);
}
function series(min,max)
{
var i = min; var s = [];
while (s[s.length-1] < max) s[s.length]=i++;
return s;
}
You can use a helper random number to whether generate random numbers in 40-60 or 1-100:
// 90% of random numbers should be between 40 to 60.
var weight_percentage = 90;
var focuse_on_center = ( (Math.random() * 100) < weight_percentage );
if(focuse_on_center)
{
// generate a random number within the 40-60 range.
alert (40 + Math.random() * 20 + 1);
}
else
{
// generate a random number within the 1-100 range.
alert (Math.random() * 100 + 1);
}
If you can use the gaussian function, use it. This function returns normal number with average 0 and sigma 1.
95% of this number are within average +/- 2*sigma. Your average = 50, and sigma = 5 so
randomNumber = 50 + 5*gaussian()
The best way to do that is generating a random number that is distributed equally in a certain set of numbers, and then apply a projection function to the set between 0 and a 100 where the projection is more likely to hit the numbers you want.
Typically the mathematical way of achieving this is plotting a probability function of the numbers you want. We could use the bell curve, but let's for the sake of easier calculation just work with a flipped parabola.
Let's make a parabola such that its roots are at 0 and 100 without skewing it. We get the following equation:
f(x) = -(x-0)(x-100) = -x * (x-100) = -x^2 + 100x
Now, all the area under the curve between 0 and 100 is representative of our first set where we want the numbers generated. There, the generation is completely random. So, all we need to do is find the bounds of our first set.
The lower bound is, of course, 0. The upper bound is the integral of our function at 100, which is
F(x) = -x^3/3 + 50x^2
F(100) = 500,000/3 = 166,666.66666 (let's just use 166,666, because rounding up would make the target out of bounds)
So we know that we need to generate a number somewhere between 0 and 166,666. Then, we simply need to take that number and project it to our second set, which is between 0 and 100.
We know that the random number we generated is some integral of our parabola with an input x between 0 and 100. That means that we simply have to assume that the random number is the result of F(x), and solve for x.
In this case, F(x) is a cubic equation, and in the form F(x) = ax^3 + bx^2 + cx + d = 0, the following statements are true:
a = -1/3
b = 50
c = 0
d = -1 * (your random number)
Solving this for x yields you the actual random number your are looking for, which is guaranteed to be in the [0, 100] range and a much higher likelihood to be close to the center than the edges.
This answer is really good. But I would like to post implementation instructions (I'm not into JavaScript, so I hope you will understand) for different situation.
Assume you have ranges and weights for every range:
ranges - [1, 20], [21, 40], [41, 60], [61, 100]
weights - {1, 2, 100, 5}
Initial Static Information, could be cached:
Sum of all weights (108 in sample)
Range selection boundaries. It basically this formula: Boundary[n] = Boundary[n - 1] + weigh[n - 1] and Boundary[0] = 0. Sample has Boundary = {0, 1, 3, 103, 108}
Number generation:
Generate random number N from range [0, Sum of all weights).
for (i = 0; i < size(Boundary) && N > Boundary[i + 1]; ++i)
Take ith range and generate random number in that range.
Additional note for performance optimizations. Ranges don't have to be ordered neither ascending nor descending order, so for faster range look-up range that has highest weight should go first and one with lowest weight should go last.
So I've been working on re-producing the slider found here https://www.skylight.io/ ( Scroll down to find the price slider ).
So far Ive managed to create something similiar, but some numbers are hard coded, making it difficult to change and not very re-usable.
I've been researching around and I think I need to use Math.log() and Math.exp() together to achieve something like in the link above but I'm not sure.
Heres a jsfiddle of what I have so far https://jsfiddle.net/7wrvpb34/.
I feel that its the maths part of this problem that is halting me I think, so any help would be greatly appreciated.
Javascript code below:
var slider = document.getElementById("slider")
var sliderFill = document.getElementById("slider-fill")
var knob = document.getElementById("knob")
var mouseDown;
var mousePos = {x:0};
var knobPosition;
var minPrice = 20;
var price = 0;
var minRequests = 50;
var requests = 50 + ",000";
var incrementSpeed = 2;
var incrementModifier = 20;
var incrementValue = 1;
var minMillionCount = 1;
var millionCount = 1;
var previousRequestAmount = 0;
document.getElementById("price").innerHTML = price;
document.getElementById("requests").innerHTML = requests;
highlightTable(1);
document.addEventListener('mousemove', function(e) {
if(mouseDown) {
updateSlider(e);
}
})
function updateSlider(event) {
mousePos.x = event.clientX - slider.getBoundingClientRect().left;
mousePos.x -= knob.offsetWidth / 2;
console.log(mousePos.x);
if(mousePos.x < 0) {
knob.style.left = "0px";
sliderFill.style.width = "0px";
price = 0;
requests = 50 + ",000";
document.getElementById("price").innerHTML = price;
document.getElementById("requests").innerHTML = requests;
return
}
if(mousePos.x > slider.offsetWidth - 20) {
return
}
sliderFill.style.width = mousePos.x + 10 + "px";
knob.style.left = mousePos.x + "px";
//Increase requests by using X position of mouse
incrementSpeed = mousePos.x / incrementModifier;
requests = minRequests + (mousePos.x * incrementSpeed);
//Round to nearest 1
requests = Math.round(requests / incrementValue) * incrementValue;
if (requests >= 1000){
var m = requests/ 1000;
m = Math.round(m / 1) * 1;
//Problem, lower the modifier depending on requests
incrementModifier = 20 * 0.95;
document.getElementById("requests").innerHTML = m + " million";
//Adjust Prices
if(( requests >= 1000) && (requests < 10000)) {
var numOfMillions = requests / 100;
//Round to closest 10.
//10 * number of millions
var rounded = Math.round(numOfMillions / 10) * 10;
price = minPrice + rounded;
highlightTable(3);
}
//Adjust Prices
if(requests >= 10000) {
var numOfMillions = requests / 1000;
var rounded = Math.round(numOfMillions / 1) * 1;
var basePrice = minPrice * 6;
price = basePrice + rounded;
highlightTable(4);
}
} else {
incrementModifier = 20;
document.getElementById("requests").innerHTML = requests + ",000"
if(requests < 100) {
highlightTable(1);
price = 0;
} else {
highlightTable(2);
price = 20;
}
}
previousRequestAmount = requests;
document.getElementById("price").innerHTML = price;
}
knob.addEventListener('mousedown', function() {
mouseDown = true;
});
document.addEventListener('mouseup', function() {
mouseDown = false;
});
function highlightTable(rowNum) {
var table = document.getElementById("payment-table")
for(var i = 0; i < table.rows.length; ++i) {
var row = table.rows[i]
if(i == rowNum) {
row.style.background = "grey"
} else {
row.style.background = "white";
}
}
}
Thank you for your time.
If you want it to be reusable you need to create a mathematical function that assigns a result to the number of requests. I will give you a very easy example.
If you want a different result for 1,10,100,100,10000 etc
var d = Math.log10(requests);
if(d<1){
doSomething();
}else if(d<2){
doSomethingElse();
} //etc
This way if you want to change the specific values that create certain results, all you need to do is change the function.
This only works if your tiers of requests follow a math function, if they don't you need to hard code it.
However if say they don't follow a math function, but you know how you would like them to change based on a value then you can do this.
var changingValue = 4;
if(requests < 400*changingValue){
doSomthing();
}else if(requests <= 400*changingValue*changingValue){
doSomethingElse();
}else{// the requests is greater than any of the above
doTheOtherThing();
}
Edit:
For the second one you need to make sure that each condition if always larger than the other from top to bottom.
The description "increasingly increasing" matches an arbitrary number of functions. I assume you also want it to be continuous, since you already have a non-continuous solution.
TL;DR
Use an exponential function.
Generic approach
Assuming imin and imax are the minimal and maximal values of the slider (i for input) and omin and omax are the minimal and maximal values to be displayed, the simplest thing I can think of would be a multiplication by something based on the input value:
f(x)
{
return omin + (omax - omin) * g((x - imin) / (imax - imin));
}
This will pass 0 to g if x == imin and 1 if x == imax.
The return value r of g(y) should be
r == 0 for y == 0
r == 1 for y == 1
0 < r < y for 0 < y < 1
The simplest function that I can think of that fulfills this is an exponential function with exponent > 1.
An exponent of 1 would be a linear function.
An exponent of 2 would be make the middle of the slider display one fourth of the maximum price instead of half of it.
But you really need to find that exponent yourself, based on your needs.