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;
}
Related
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);
}
I want to round a number to the nearest 0.5. Not every factor of 0.5, just the 0.5s.
For example, 0.5, 1.5, 2.5, -1.5, -2.5. NOT 1, 1.5, 2, 2.5.
I'm confusing myself just explaining it, so here are some examples of expected outputs.
0.678 => 0.5
0.999 => 0.5
1.265 => 1.5
-2.74 => -2.5
-19.2 => -19.5
I have tried the following code with no luck,
let x = 1.296;
let y = Math.round(x);
let z = y + Math.sign(y) * .5; // 1.5 (Correct!)
let x = -2.6;
let y = Math.round(x);
let z = y + Math.sign(y) * .5; // -3.5 (WRONG, should be -2.5)
The code makes sense in my head, but dosen't work for negative numbers. What am I missing that would make this work?
First, you can round to integer by
let x = 1.296;
let y = Math.round(x);
Then, you can subtract 0.5 first, then round, then add 0.5
let x = 1.296;
let y = Math.round(x-0.5);
let z = y + 0.5;
function getValue (a){
var lowerNumber = Math.floor(a);
console.log(lowerNumber +0.5);
}
getValue(0.678);
getValue(0.999);
getValue(1.265);
getValue(-2.74);
getValue(-19.2);
looks like you want lower full number + 0.5 ;
You can try this logic:
Get the decimal part from number.
Check if value is positive or negative. Based on this initialise a factor
For positive keep it 1
For negative keep it -1
Multiply 0.5 with factor and add it to decimal
var data = [ 0.678, -0.678, 0.999, 1.265, -2.74, -19.2 ]
const output = data.map((num) => {
const decimal = parseInt(num)
const factor = num < 0 ? -1 : 1;
return decimal + (0.5 * factor)
})
console.log(output)
So I have a variable containing rotation in degrees, and I have an ideal rotation, and what I want is the percentage of accuracy within 20 degrees in either direction.
var actualRotation = 215
var idealRotation = 225
var accuracy = magicFunction(actualRotation, idealRotation)
In this case, the actualRotation is 10 degrees off from idealRotation, so with a 20 degree threshold in either direction, that's a 50% accuracy. So the value of accuracy would be 0.5.
var accuracy = magicFunction(225, 225) // 1.0
var accuracy = magicFunction(225, 210) // 0.25
var accuracy = magicFunction(245, 225) // 0.0
var accuracy = magicFunction(90, 225) // 0.0
How can I achieve this?
var actualRotation = 215
var idealRotation = 225
var diff = abs(actualRotation - idealRotation);
if (diff > 20)
console.log(0);
else{
accuracy = 1 - (diff/ 20);
console.log(accuracy);
}
Try this (just run code snippet):
function magicFunction(actualRotation , idealRotation ) {
var diff = Math.abs(actualRotation - idealRotation);
var accurrancy = 1 - (diff / 20);
accurrancy = accurrancy < 0 ? 0 : accurrancy;
return accurrancy;
}
console.log("225, 225: ", magicFunction(225, 225));
console.log("225, 210: ", magicFunction(225, 210));
console.log("245, 225: ", magicFunction(245, 225));
console.log("90, 225: ", magicFunction(90, 225));
The previous answers were good, but they don't handle the case where the difference crosses the zero-singularity.
E.g. when the angles are 5 and 355, you expect a difference of 10, but a simple subtraction gives 350. To rectify this, subtract the angle from 360 if it is bigger than 180.
For the above to work, you also need the angles to be in the range [0, 360). However this is a simple modulo calculation, as below.
Code:
function normalize(angle) {
if (angle < 0)
return angle - Math.round((angle - 360) / 360) * 360;
else if (angle >= 360)
return angle - Math.round(angle / 360) * 360;
else
return angle;
}
function difference(angle1, angle2) {
var diff = Math.abs(normalize(angle1) - normalize(angle2));
return diff > 180 ? 360 - diff : diff;
}
function magicFunction(actualRotation, idealRotation, limit) {
var diff = difference(actualRotation, idealRotation);
return diff < limit ? 1.0 - (diff / limit) : 0.0;
}
// tests
console.log(difference(10, 255)); // 115 (instead of the incorrect answer 245)
console.log(magicFunction(5, 355, 20)); // 0.5 (instead of 0 as would be returned originally)
EDIT: a graphical illustration of why the previous method would be insufficient:
Is it possible to calculate a color in a middle of a gradient?
var color1 = 'FF0000';
var color2 = '00FF00';
// 50% between the two colors, should return '808000'
var middle = gradient(color1, color2, 0.5);
I only have two hex strings, and I want one in return.
This should work:
It basically involves converting them to decimal, finding the halves, converting the results back to hex and then concatenating them.
var color1 = 'FF0000';
var color2 = '00FF00';
var ratio = 0.5;
var hex = function(x) {
x = x.toString(16);
return (x.length == 1) ? '0' + x : x;
};
var r = Math.ceil(parseInt(color1.substring(0,2), 16) * ratio + parseInt(color2.substring(0,2), 16) * (1-ratio));
var g = Math.ceil(parseInt(color1.substring(2,4), 16) * ratio + parseInt(color2.substring(2,4), 16) * (1-ratio));
var b = Math.ceil(parseInt(color1.substring(4,6), 16) * ratio + parseInt(color2.substring(4,6), 16) * (1-ratio));
var middle = hex(r) + hex(g) + hex(b);
An ES6 version with comprehensions:
function interpolateColor(c0, c1, f){
c0 = c0.match(/.{1,2}/g).map((oct)=>parseInt(oct, 16) * (1-f))
c1 = c1.match(/.{1,2}/g).map((oct)=>parseInt(oct, 16) * f)
let ci = [0,1,2].map(i => Math.min(Math.round(c0[i]+c1[i]), 255))
return ci.reduce((a,v) => ((a << 8) + v), 0).toString(16).padStart(6, "0")
}
As in the accepted answer, c0,c1 are color codes (without the leading #) and f is "progress" between the two values. (At f=0 this ends up returning c0, at f=1 this returns c1).
The first two lines convert the color codes into arrays of scaled integers
The third line:
"zips" the two integer arrays
sums the corresponding values
rounds the sum and clamps it to 0-255
The fourth line:
converts the integer array into a single integer (reduce and bitshifting)
converts the integer into its hexadecimal string form
ensures the resulting string is 6 characters long and returns it
I can't comment on the answer above, so I write it here:
I found out that in the Javascript substring method the to parameter index is not included in the returned string. That means:
var string = "test";
//index: 0123
alert(string.substring(1,3));
//will alert es and NOT est
Edit: So it should be:
parseInt(color1.substring(0,2), 16);
parseInt(color1.substring(2,4), 16);
and
parseInt(color1.substring(4,6), 16);
You can use this ready function (ES6):
const calculateMiddleColor = ({
color1 = 'FF0000',
color2 = '00FF00',
ratio,
}) => {
const hex = (color) => {
const colorString = color.toString(16);
return colorString.length === 1 ? `0${colorString}` : colorString;
};
const r = Math.ceil(
parseInt(color2.substring(0, 2), 16) * ratio
+ parseInt(color1.substring(0, 2), 16) * (1 - ratio),
);
const g = Math.ceil(
parseInt(color2.substring(2, 4), 16) * ratio
+ parseInt(color1.substring(2, 4), 16) * (1 - ratio),
);
const b = Math.ceil(
parseInt(color2.substring(4, 6), 16) * ratio
+ parseInt(color1.substring(4, 6), 16) * (1 - ratio),
);
return hex(r) + hex(g) + hex(b);
};
//////////////////////////////////////////////////////////////////////
console.log(calculateMiddleColor({ ratio: 0 / 5 })); // ff0000
console.log(calculateMiddleColor({ ratio: 5 / 5 })); // 00ff00
console.log(calculateMiddleColor({ ratio: 2.5 / 5 })); // 808000
console.log(calculateMiddleColor({ ratio: 4.2 / 5 })); // 29d700
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;