JavaScript: Round to the nearest value on a scale - javascript

Lets say I have a scale with 10 values between a know min and max value. How can I get the nearest value on the scale for value between min and max. Example:
min = 0, max = 10, value = 2.75 -> expected: value = 3
min = 5, max = 6, value = 5.12 -> expected: value = 5.1
min = 0, max = 1, value = 0.06 -> expected: value = 0.1

You could use something like this
function nearest(value, min, max, steps) {
var zerone = Math.round((value - min) * steps / (max - min)) / steps; // bring to 0-1 range
zerone = Math.min(Math.max(zerone, 0), 1) // keep in range in case value is off limits
return zerone * (max - min) + min;
}
console.log(nearest(2.75, 0, 10, 10)); // 3
console.log(nearest(5.12, 5, 6, 10)); // 5.1
console.log(nearest(0.06, 0, 1, 10)); // 0.1
Demo at http://jsfiddle.net/gaby/4RN37/1/

Your scenario doesn't make much sense to me. Why does .06 round to 1 and not .1 but 5.12 rounds to 5.1 with the same scale (1 integer)? It's confusing.
Either way, if you want to round to a precise # of decimal places, check this out:
http://www.javascriptkit.com/javatutors/round.shtml
var original=28.453
1) //round "original" to two decimals
var result=Math.round(original*100)/100 //returns 28.45
2) // round "original" to 1 decimal
var result=Math.round(original*10)/10 //returns 28.5
3) //round 8.111111 to 3 decimals
var result=Math.round(8.111111*1000)/1000 //returns 8.111
With this tutorial, you should be able to do exactly what you want.

Perhaps more comprehensible:
var numberOfSteps = 10;
var step = (max - min) / numberOfSteps;
var difference = start - min;
var stepsToDifference = Math.round(difference / step);
var answer = min + step * stepsToDifference;
This also allows you to change the number of steps in your sequence.

I suggest something like that :
var step = (max - min) / 10;
return Math.round(value / step) * step;

I had the problem where I was getting 5.7999997 instead of the weanted 5.8 for example. Here was my first fix (for java...).
public static float nearest(float val, float min, float max, int steps) {
float step = (max - min) / steps;
float diff = val - min;
float steps_to_diff = round(diff / step);
float answer = min + step * steps_to_diff;
answer = ((int) (answer * steps)) / (float) steps;
return answer;
}
However using this on nearest(6.5098, 0, 10, 1000) I would get 6.509 instead of the wanted 6.51.
This solved it for me (watch out for overflows when values are really large):
public static float nearest(float val, float min, float max, int steps) {
val *= steps;
min *= steps;
max *= steps;
float step = (max - min) / steps;
float diff = val - min;
float steps_to_diff = round(diff / step);
float answer = min + step * steps_to_diff;
return answer / (float) steps;
}

var step = 10;
return Math.ceil(x / step) * step;

Related

How do I make this function more precise?

I'm a beginner and I made a function to calculate the length of a semi-circular infinite snake figure. I took in two arguments; one of the radius the initial circle, and the next to be the precision (which is just the number of semi-circles).
Here's a diagram of the snake I'm talking about.
Here's what I wrote:
function snake(radius, precision) {
var pi = 3.14159265359
var exp = 1 - precision;
var sub = Math.pow(2, exp);
var product = 2 - sub;
var length = pi * radius * product
return length
}
I'm noticing that at one point the precision doesn't matter when I go really high as the value it return is the same. Is there a way to make it more precise?
You may use the constant Math.PI instead of your pi variable.
Feels like Number.toPrecision() is what you are looking for.
Below is slightly cleaned up version of your code snippet.
For the return value I'm using length.toPrecision(50):
function snake(radius, precision) {
const exp = 1 - precision;
const sub = Math.pow(2, exp);
const product = 2 - sub;
const length = Math.PI * radius * product;
return length.toPrecision(50);
}
console.log(snake(5, 55));
Yo can find out more about toPrecision() here.
The max precision value is 100.
This will be my method,
Length can be get by sum of the below series according to the screen shot,
PI X R (1 + 1/2 + 1/4 + ...)
S(n) = PIxR(1-0.5^n)/(1-0.5)
So the JavaScript function is,
function length(r, n) {
const ln = Math.PI * r * (1 - Math.pow(0.5, n))/(1 - 0.5);
return ln.toPrecision(50);
}

var flip = Math.floor(Math.random() * (1 - 0 + 1)) + 0;?

I found some code snippets and I'm not sure what it means:
var flip = Math.floor(Math.random() * (1 - 0 + 1)) + 0;
and
Math.floor(Math.random() * (max - min + 1)) + min
I'm still getting familiar with Javascript... could someone give me a reader's digest condensed version?
Math.floor() Round a number downward to its nearest integer
For example: if you have 2.7 it will round down to 2.
Math.random() Return a random number between 0 and 1
For example: .693

Weighted Random Number Generator in Javascript

I am using the following code to generate a random number:
function getRandomInt (min, max) {
return Math.floor((Math.random() * (max - min + 1)) + min;
}
What I want to do is add a weighting that favours the numbers at the lower end of the range.
I thought about maybe trying to multiply the numbers by 1/cosine.
Would this work and does anyone know how I might go about it?
Many thanks!
First Solution
You need a function which contains the points (0, 0) and (1, 1). For instance: x^n when n > 0
Math.pow(1, n) === 1
And
Math.pow(0, n) === 0
Therefore, you would just change n depending on how you want the weighting to work.
When n = 1 : y === x
When n > 1 : y <= x
When 0 < n < 1 : y >= x
So, if you want lower values to be favored over higher values, simply use n > 1.
var weighted = Math.pow(Math.random(), 2);
Then you can scale the result as usual.
var scaled = Math.floor(weighted * (max - min + 1)) + min;
Other Functions
Likewise, you could use any continuous function which contains the points (0, 0), (1, 1), and has range and domain of [0, 1].
Sine
y = sin(xπ/2)
Cosine
y = 1 - cos(xπ/2)
EDIT: there was a type in the final formula, log(2+log(x)) is incorrect it should have been log(1+log(x))+1, its fixed now.
If you are using logarithmic weighting, using something like
var x = Math.random();
var weighted = x * Math.log(1+x);
would make 0.5 weigh in at around 0.2, but 1 would only weigh in at around 0.69.
Using this
var x = Math.random();
var weighted = x * Math.log(2 + Math.log(x));
would allow 1 to weigh in at 1. So combine them, and this
var x = Math.random();
var weighted = (x <= 0.5) ? x * Math.log(1 + x) : x * Math.log(1 + Math.log(x))+1;
should do the trick

What the valid range of HSV color

I'm playing with HSV color. I have an array of hsv after convert from rgb color:
//hsv[0], hsv[1], hsv[2]
var hsv = rgbToHsv(rgb[0], rgb[1], rgb[2]);
I will add or subtract it
hsv[0] += ...
hsv[1] += ...
hsv[2] += ...
And I need to valid the value before convert it back to rgb. What is the valid range of hsv?
Here is the function I using to convert rgb to hsv
function rgbToHsv(r, g, b) {
var r = (r / 255),
g = (g / 255),
b = (b / 255);
var min = Math.min(Math.min(r, g), b),
max = Math.max(Math.max(r, g), b),
delta = max - min;
var value = max,
saturation,
hue;
// Hue
if (max == min) {
hue = 0;
} else if (max == r) {
hue = (60 * ((g-b) / (max-min))) % 360;
} else if (max == g) {
hue = 60 * ((b-r) / (max-min)) + 120;
} else if (max == b) {
hue = 60 * ((r-g) / (max-min)) + 240;
}
if (hue < 0) {
hue += 360;
}
// Saturation
if (max == 0) {
saturation = 0;
} else {
saturation = 1 - (min/max);
}
return [(hue), (saturation * 100), (value * 100)];
}
Roughly the same algorithm is used for this online converter. You can check the article after for the opposite conversion.
H is definitely between 0 and 360, but regarding S and V it is different. Like most values for color conversion or color blending mode calculation, a float between 0 and 1 is used. I would say it is better because beeing a float means you can have all the levels of precision you want.
Now it is not uncommon (like on this online converter and your current javascript) to multiply it by 100 to get a percentage. Often rounded as well. What is important to understand with this rounding is that obviously it increases the chances of you getting a different RGB color if you convert back and forth rgb > hsv > rgb. If this is important, then you're better with the floats.
Since you are asking what is "valid", I would say it only depends on how you want to use it or where these numbers will be used.

Javascript roundoff number to nearest 0.5

Can someone give me an idea how can i round off a number to the nearest 0.5.
I have to scale elements in a web page according to screen resolution and for that i can only assign font size in pts to 1, 1.5 or 2 and onwards etc.
If i round off it rounds either to 1 decimal place or none.
How can i accomplish this job?
Write your own function that multiplies by 2, rounds, then divides by 2, e.g.
function roundHalf(num) {
return Math.round(num*2)/2;
}
Here's a more generic solution that may be useful to you:
function round(value, step) {
step || (step = 1.0);
var inv = 1.0 / step;
return Math.round(value * inv) / inv;
}
round(2.74, 0.1) = 2.7
round(2.74, 0.25) = 2.75
round(2.74, 0.5) = 2.5
round(2.74, 1.0) = 3.0
Just a stripped down version of all the above answers:
Math.round(valueToRound / 0.5) * 0.5;
Generic:
Math.round(valueToRound / step) * step;
To extend the top answer by newtron for rounding on more than only 0.5
function roundByNum(num, rounder) {
var multiplier = 1/(rounder||0.5);
return Math.round(num*multiplier)/multiplier;
}
console.log(roundByNum(74.67)); //expected output 74.5
console.log(roundByNum(74.67, 0.25)); //expected output 74.75
console.log(roundByNum(74.67, 4)); //expected output 76
Math.round(-0.5) returns 0, but it should be -1 according to the math rules.
More info: Math.round()
and Number.prototype.toFixed()
function round(number) {
var value = (number * 2).toFixed() / 2;
return value;
}
var f = 2.6;
var v = Math.floor(f) + ( Math.round( (f - Math.floor(f)) ) ? 0.5 : 0.0 );
function roundToTheHalfDollar(inputValue){
var percentile = Math.round((Math.round(inputValue*Math.pow(10,2))/Math.pow(10,2)-parseFloat(Math.trunc(inputValue)))*100)
var outputValue = (0.5 * (percentile >= 25 ? 1 : 0)) + (0.5 * (percentile >= 75 ? 1 : 0))
return Math.trunc(inputValue) + outputValue
}
I wrote this before seeing Tunaki's better response ;)
These answers weren't useful for me, I wanted to always round to a half (so that drawing with svg or canvas is sharp).
This rounds to the closest .5 (with a bias to go higher if in the middle)
function sharpen(num) {
const rem = num % 1
if (rem < 0.5) {
return Math.ceil(num / 0.5) * 0.5 + 0.5
} else {
return Math.floor(num / 0.5) * 0.5
}
}
console.log(sharpen(1)) // 1.5
console.log(sharpen(1.9)) // 1.5
console.log(sharpen(2)) // 2.5
console.log(sharpen(2.5)) // 2.5
console.log(sharpen(2.6)) // 2.5
The highest voted answer above fails for:
roundHalf(0.6) => returns 0.5
roundHalf(15.27) => returns 15.5
The fixed one is as follows:
const roundHalf = (num) => {
return Math.floor(Math.ceil(num * 2) / 2)
}
As a bit more flexible variation of the good answer above.
function roundNumber(value, step = 1.0, type = 'round') {
step || (step = 1.0);
const inv = 1.0 / step;
const mathFunc = 'ceil' === type ? Math.ceil : ('floor' === type ? Math.floor : Math.round);
return mathFunc(value * inv) / inv;
}

Categories

Resources