I have an increasing value 1 to 10000. I can put this in a sin function to get values like a sin output.
Now I want a linear output, that when I give this value as input it gives me output like this: Actually the values has to be in 0..1 range
0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .8 .7 .6 .5 .4 .3 .2 .1 0
How can I do this fast math way
Long
Actually I want a period of zeros and then a sudden burst to 1 and than a calm down to 0 again. I thought if I get the above version I can put that in an easing function to get this result:
0 0 0 0 0 0 .1 .2 .4 .8 .9 1 .9 .8 .4 .2 .1
A non performant slow way to do this is:
const linear = (() => {
const res = [];
for (let i = 0; i < 100; i++) {
res.push(i / 100);
}
for (let i = 100; i > 0; i--) {
res.push(i / 100);
}
return t => res[Math.round(t) % res.length];
})();
const easing = t => {
return .04 * t / (--t) * Math.sin(25 * t);
};
Use it like easing(linear(t))
Related
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:
I know how to generate a random number between two numbers. But what I'd like to achieve is a way to generate a number between two numbers in a not totally random way. Let me explain...
So I have a function that generates a color based on a number passed into it. If that number is between 0 and 600, I'd like it to pass a number between 0 and 120 to the hue of the hsl value. If the number is greater than 600, I'd like a number between 120 and 240 passed to the hue of the hsl value. My function looks something like this:
getColor:function (number {
var hue;
var color;
if (number <= 600) {
hue = [A number between 0 and 120];
} else if (number >= 600) {
hue = [A number between 120 and 240];
}
color = 'hsl(' + hue + ', 100%, 80%)'
return color;
}
So the higher the number passed into the function, for example, between 0 and 600, the higher the hue value between 0 and 120. That make sense?
Thx u
-- Gaweyne
Simple Math:
hue = Math.floor(number * 120 / 600);
Or with both points:
function transpose(smin, smax, dmin, dmax) {
var slen = smax - smin;
var dlen = dmax - dmin;
var ratio = dlen / slen;
return function(num) {
return num * ratio + smin;
}
}
transpose(0, 600, 0, 120)(300); // 60
Ok first of all you should know the maximum and minimum values of number. In my example The maximum value of number will be 1200 and the minimum 0, so the range is between 0 and 1200. And the range of hue is between 0 and 240.
the higher the number passed into the function, the higher the hue value.
0 hue = 0 number;
120 hue = 600 number;
240 hue = 1200 number;
=> 1 hue = (600 / 120) number = (1200 / 240) number
=> 1 hue = 5 number
In my example, (with number between 0 and 1200 and 600 is the middle) 1 value in hue is equal to 5 value in number. So :
hue = number / 5;
if you want hue to be an integer just use Math :
hue = Math.floor(number / 5);
In my example hue will grow up by 1 every time you add 5 to number, it doesn't matter if number is less or more than 600 because the range of number on both sides of 600 is the same (600 is in the middle of the range). In case this is not what you want, and 600 is not in the middle of the range, you will have to do the same calculation above twice.
var max = [maximum value of number];
var min = [minimum value of number];
getColor:function (number {
var hue;
var color;
if (number <= 600) {
hue = Math.floor( number / ((600 - min) / 120) );
} else if (number >= 600) {
hue = Math.floor( number / ((max - 600) / 120) ) + 120;
}
color = 'hsl(' + hue + ', 100%, 80%)';
return color;
}
I have a component that returns me a value from 0 to 360 degrees, I need to pass that value to units, for example from 0 to 100.
I have the following function but it seems ugly
function degToValue( deg )
{
var unit = Math.ceil( ( deg * 100 ) / 360 );
if ( unit === 0 ) unit = 100;
if ( deg < 1.6 && deg > 0 ) unit = 0;
return unit;
}
Do you know a more elegant way?
You can divide by 3.6 and use modulus to make this much prettier:
function degToValue( deg )
{
var unit = (deg / 3.6) % 100;
return (unit === 0 ? 100 : unit);
}
console.log( degToValue( 360 )); //100
console.log( degToValue( 0 )); //100
console.log( degToValue( 355 )); //98.61
console.log( degToValue( 719 )); //99.72
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;
}