Rounding to nearest 100 - algorithm

First number needs to be rounded to nearest second number. There are many ways of doing this, but whats the best and shortest algorithm? Anyone up for a challenge :-)
1244->1200
1254->1300
123->100
178->200
1576->1600
1449->1400
123456->123500
654321->654300
23->00
83->100

Ruby's round method can consume negative precisions:
n.round(-2)
In this case -2 gets you rounding to the nearest hundred.

For input n:
(n + 50) / 100 * 100
using integer division.
Note that many languages/libraries already have functions to do this.

100 * round(n/100.0)

I know it's late in the game, but here's something I generally set up when I'm dealing with having to round things up to the nearest nTh:
Number.prototype.roundTo = function(nTo) {
nTo = nTo || 10;
return Math.round(this * (1 / nTo) ) * nTo;
}
console.log("roundto ", (925.50).roundTo(100));
Number.prototype.ceilTo = function(nTo) {
nTo = nTo || 10;
return Math.ceil(this * (1 / nTo) ) * nTo;
}
console.log("ceilTo ", (925.50).ceilTo(100));
Number.prototype.floorTo = function(nTo) {
nTo = nTo || 10;
return Math.floor(this * (1 / nTo) ) * nTo;
}
console.log("floorTo ", (925.50).floorTo(100));
I find myself using Number.ceilTo(..) because I'm working with Canvas and trying to get out to determine how far out to scale.

This will do it, given you're using integer math:
n = (n + 50) / 100 * 100
Of course, you didn't specify the behavior of e.g., 1350 and 1450, so I've elected to round up. If you need round-to-even, that'll not work.

As per Pawan Pillai's comment above, rounding to nearest 100th in Javascript:
100 * Math.floor((foo + 50) / 100);

Is this homework?
Generally, mod 100, then if >50 add else subtract.

Related

work out how many seconds have expired in total during game play

~Why the hell has this had down votes.... you people are weird!
Ok so this is a very simply HTML5 and jQuery and PHP game. Sorry to the people who have answered, I forgot to say this is a php script, i have updated here to reflect.
the first level takes 1 minute. Every level after that takes an extra 10 seconds than the last level. like so;
level 1 = 60 seconds
level 2 = 70 seconds
level 3 = 80 seconds
level 4 = 90 seconds
and so on infinitely.
I need an equation that can figure out what is the total amount of seconds played based on the users level.
level = n
i started with (n * 10) + (n * 60) but soon realized that that doesn't account for the last level already being 10 seconds longer than the last. I have temporarily fixed it using a function calling a foreach loop stopping at the level number and returning the value. but i really want an actual equation.
SO i know you wont let me down :-)
Thanks in advance.
this is what i am using;
function getnumberofsecondsfromlevel($level){
$lastlevelseconds = 60;
while($counter < $level){
$totalseconds = $lastlevelseconds+$totalseconds;
$lastlevelseconds = $lastlevelseconds + 10;
$counter++;
}
return $totalseconds;
}
$level = $_SESSION['**hidden**']['thelevel'];
$totaldureationinseconds = getnumberofsecondsfromlevel($level);
but i want to replace with an actual equation
like so;(of course this is wrong, this is just the example of the format i want it in i.e an equation)
$n = $_SESSION['**hidden**']['thelevel']; (level to get total value of
in seconds)
$s = 60; (start level)
$totaldureationinseconds = ($n * 10) + ($s * $n);
SOLVED by Gopalkrishna Narayan Prabhu :-)
$totalseconds = 60 * $level + 5* (($level-1) * $level);
var total_secs = 0;
for(var i = 1; i<= n ;i++){
total_secs = total_secs + (i*10) + 50;
}
for n= 1, total_secs = 0 + 10 + 50 = 60
for n= 2, total_secs = 60 + 20 + 50 = 130
and so on...
For a single equation:
var n = level_number;
total_secs = 60 * n + 5* ((n-1) * n);
Hope this helps.
It seems as though you're justing looking for the equation
60 + ((levelN - 1) * 10)
Where levelN is the current level, starting at 1. If you make the first level 0, you can get rid of the - 1 part and make it just
60 + (levelN * 10)
Thought process:
What's the base/first number? What's the lowest it can ever be? 60. That means your equation will start with
60 + ...
Every time you increase the level, you add 10, so at some point you'll need something like levelN * 10. Then, it's just some fiddling. In those case, since you don't add any on the first left, and the first level is level 1, you just need to subtract 1 from the level number to fix that.
You can solve this with a really simple mathematical phrase (with factorial).
((n-1)! * 10) + (60 * n)
n is the level ofcourse.

Does d3.js have reverse ease functions?

With d3.js we can achieve eased time out of normalized time t, typically in the range [0,1]
For example:
d3.easeCubic(0.25) = 0.0625
How can we reverse that, how can we find x given known y ?
d3.easeCubic(X) = 0.0625,
X ???
The answer here is cubic root, but still.
The problem is in reusability, ease function can change to d3.easeExpIn, or `d3.easeCircleOut, or any other, do you need to invent reverse functions on your own, or are they hidden anywhere ?
Firstly, your math is wrong. d3.easeCubic(0.25) will give you 0.0625:
var easy = d3.easeCubic(0.25);
console.log(easy);
<script src="https://d3js.org/d3.v4.min.js"></script>
Now, back to your question:
How can we reverse that, how can we find x given known y?
There is no native solution, but we can create our own function to find X given a known Y. The problem, of course, is that we have to invert the math for each specific easing... But, since you asked about d3.easeCubic, which is the same of d3.easeCubicInOut, let's try to create an inverted function for that particular easing.
First step, let's have a look at the source code:
export function cubicInOut(t) {
return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2;
}
You can easily see that this is the correct function, giving us the same value as the first snippet:
function cubicInOut(t) {
return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2;
}
console.log(cubicInOut(0.25))
Now, let's try to invert it.
The math here is somehow complicated, but for values less than 1, here is the function:
function inverseEaseCubic(t){
return Math.cbrt(t * 2) / 2;
}
And here is the demo. We pass 0.0625 to the function, and it returns 0.25:
function inverseEaseCubic(t){
return Math.cbrt(t * 2) / 2;
}
console.log(inverseEaseCubic(0.0625))
If you want to deal with numbers bigger than 1, this is the complete function:
function InverseEaseCubic(t){
return t <= 1 ? Math.cbrt(t * 2) / 2 : (Math.cbrt(2 * t - 2) + 2) / 2;
}
PS: In his comment, #altocumulus just reminded us that, sometimes, it's even impossible to find the value. Here is a very simple example. Suppose this function:
function exponentiation(a){
return a*a;
}
Now imagine that, when called with an unknown argument, the function returned 4. What's the argument? Can we find out? Impossible to determine, because second degree equations, like this one, have 2 roots:
console.log(exponentiation(2))//returns 4
console.log(exponentiation(-2))//also returns 4
I used the #Gerardo Furtado answer but the inverse function didn't work well so I wrote another
function cubicInOut(t) {
return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2;
}
function inverseEaseCubic(x) {
return x < .5 ? Math.cbrt(x / 4) : (2 - Math.cbrt(2 - 2 * x)) / 2;
}
console.log(inverseEaseCubic(cubicInOut(1)) === 1);
console.log(inverseEaseCubic(cubicInOut(0.6)) === 0.6);
console.log(inverseEaseCubic(cubicInOut(0.4)) === 0.4);
console.log(inverseEaseCubic(cubicInOut(0.1)) === 0.1);
console.log(inverseEaseCubic(cubicInOut(0)) === 0);

Take exact root of value

I'd like to know how you can take the exact n-th root of a number (in any programming language). When I use a physical calculator, I can type something like sqrt(12) (nicely formatted of course) and get as a result 2 sqrt(3). How can I achieve this not only with square roots but any type of root when representing a number as numerator and denominator. Of course, I would have to use another representation, but I don't have any idea how this works in general.
Thanks in advance.
I doubt this is an efficient way, but it would work. Assuming you want to take the nth root of some number m:
Calculate the prime factorization m = p1a1 * p2a2 * ... * pxax.
For each 1 <= i <= x let ki = ai div n and ri = ai mod n.
The part that gets factored out is then p1k1 * p2k2 * ... * pxkx.
The part that remains "under the root" is p1r1 * p2r2 * ... * pxrx.
The first step is the only tricky one. Once you have found all prime factors of m it is just a matter of looping over those factors and dividing out the multiples of n.
To simplify the n-th root of a number, the algorithm shouldn't do prime factorisation, but rather "n-th power factorisation", i.e. look for the largest n-th power inside the root, which you can then move outside the root. For example: the 3rd root of 250 equals the third root of 2 x 125; since 125 is the third power of 5, you can move it out of the root and get: 5 times the third root of 2.
Algorithm: take the floating-point n-th root of the number, and round it down, then check this and all smaller integers until you find the largest integer whose n-th power divides the number; then divide the number by the n-th power and move the integer out of the root.
This javascript example shows a basic implementation; you could clean it up further by printing 11/root simply as 1; further optimisation is undoubtedly possible.
function integerRoot(number, root) {
var base = number, factor = 1;
var max = Math.floor(Math.pow(base, 1/root));
for (var i = max; i > 1; i--) {
var power = Math.pow(i, root);
if (base % power == 0) {
base /= power;
factor *= i;
break;
}
}
document.write(number + "<SUP>1/" + root + "</SUP> = " +
factor + " × " + base + "<SUP>1/" + root + "</SUP><BR>");
}
integerRoot(25, 3);
integerRoot(27, 3);
integerRoot(81, 3);
integerRoot(135, 3);
integerRoot(375, 3);
integerRoot(8*27*64*17, 3);
UPDATE: This is a more efficient version; I haven't yet taken negative numbers into account, though, so there's definitely room for further improvement.
function simplifyRoot(radicand, degree) {
var factor = 1, base = 1, power;
while ((power = Math.pow(++base, degree)) <= radicand) {
while (radicand % power == 0) {
factor *= base;
radicand /= power;
}
}
return {factor: factor, radicand: radicand, degree: degree};
}
var radicand = 8*27*36*64*125*216, degree = 3;
var simplified = simplifyRoot(radicand, degree);
document.write(radicand + "<SUP>1/" + degree + "</SUP> = " +
simplified.factor + " × " + simplified.radicand + "<SUP>1/" + simplified.degree + "</SUP><BR>");

Quiz scoring algorithm for how close an answer is

I am trying to generate a small algorithm that will give a user a decimal score out of 1 based on how close their answer is to a true answer. These answers will always be numeric and be things like 'How many x did this?'
I will be setting a sensible maximum and minimum value for each answer where if a users answer exceeds this, they will score nothing though am a bit stuck on getting an equation created ...
As an example, a correct answer could be 100 and a sensible minimum could be set as 50. A user specifying 75 would thus be given a score of 0.5
Perhaps getting a bit complicated now but it would also be nice to allocate the score on a curve so the result is not linear and thus weighting is higher the nearer you are to the correct answer
Any help or better ideas for this scoring would be much appreciated
A formula code could be like this :
score = abs(input - answer) / (answer - min)
for your example we have input = 75 , answer = 100 and min = 50 so:
score = abs(75 - 100) / (100 - 50) = 25 / 50 = 0.5
If you wanted the scoring to be non-linear (to reward closeness to the answer) you could try a 'squared difference' formula. E.g.
score = 1 - (abs((answer - input)/(answer - minimum)))^2
e.g. with correct = 100, minimum = 60, answer = 70 you would get:
score = 1 - (abs((100 - 70)/(100 - 60)))^2 = 0.4375
If you want to give a greater reward for closeness, you could use a higher power. Note that division by zero will occur if answer = minimum.
I implemented the algorithm in Java and made a small test case.
public class Quiz{
public static double calculateScore(int input,
int correctAnswer,
int minimumAnswer){
if(input == correctAnswer){
return 1;
}
double correctInterval = Math.abs(correctAnswer - minimumAnswer);
double relativeAnswer = Math.abs(correctAnswer - input);
if(relativeAnswer > correctInterval){
return 0;
}else{
double score = relativeAnswer/correctInterval;
score *= score;// make ^2 to avoid a linear progression
return 1.0 - score;
}
}
}
public class QuizTest{
#Test
public void testCalculateScore() {
assertTrue(0 == Quiz.calculateScore(5, 20, 15));
assertTrue(0 == Quiz.calculateScore(30, 20, 15));
assertTrue(1 == Quiz.calculateScore(20, 20, 15));
assertTrue(0 < Quiz.calculateScore(17, 20, 15));
assertTrue(0 < Quiz.calculateScore(22, 20, 15));
assertTrue(Quiz.calculateScore(18, 20, 15) == Quiz.calculateScore(22, 20, 15));
assertTrue(Quiz.calculateScore(17, 20, 15) < Quiz.calculateScore(22, 20, 15));
}
}
The test run is successful

Tickmark algorithm for a graph axis

I'm looking for an algorithm that places tick marks on an axis, given a range to display, a width to display it in, and a function to measure a string width for a tick mark.
For example, given that I need to display between 1e-6 and 5e-6 and a width to display in pixels, the algorithm would determine that I should put tickmarks (for example) at 1e-6, 2e-6, 3e-6, 4e-6, and 5e-6. Given a smaller width, it might decide that the optimal placement is only at the even positions, i.e. 2e-6 and 4e-6 (since putting more tickmarks would cause them to overlap).
A smart algorithm would give preference to tickmarks at multiples of 10, 5, and 2. Also, a smart algorithm would be symmetric around zero.
As I didn't like any of the solutions I've found so far, I implemented my own. It's in C# but it can be easily translated into any other language.
It basically chooses from a list of possible steps the smallest one that displays all values, without leaving any value exactly in the edge, lets you easily select which possible steps you want to use (without having to edit ugly if-else if blocks), and supports any range of values. I used a C# Tuple to return three values just for a quick and simple demonstration.
private static Tuple<decimal, decimal, decimal> GetScaleDetails(decimal min, decimal max)
{
// Minimal increment to avoid round extreme values to be on the edge of the chart
decimal epsilon = (max - min) / 1e6m;
max += epsilon;
min -= epsilon;
decimal range = max - min;
// Target number of values to be displayed on the Y axis (it may be less)
int stepCount = 20;
// First approximation
decimal roughStep = range / (stepCount - 1);
// Set best step for the range
decimal[] goodNormalizedSteps = { 1, 1.5m, 2, 2.5m, 5, 7.5m, 10 }; // keep the 10 at the end
// Or use these if you prefer: { 1, 2, 5, 10 };
// Normalize rough step to find the normalized one that fits best
decimal stepPower = (decimal)Math.Pow(10, -Math.Floor(Math.Log10((double)Math.Abs(roughStep))));
var normalizedStep = roughStep * stepPower;
var goodNormalizedStep = goodNormalizedSteps.First(n => n >= normalizedStep);
decimal step = goodNormalizedStep / stepPower;
// Determine the scale limits based on the chosen step.
decimal scaleMax = Math.Ceiling(max / step) * step;
decimal scaleMin = Math.Floor(min / step) * step;
return new Tuple<decimal, decimal, decimal>(scaleMin, scaleMax, step);
}
static void Main()
{
// Dummy code to show a usage example.
var minimumValue = data.Min();
var maximumValue = data.Max();
var results = GetScaleDetails(minimumValue, maximumValue);
chart.YAxis.MinValue = results.Item1;
chart.YAxis.MaxValue = results.Item2;
chart.YAxis.Step = results.Item3;
}
Take the longest of the segments about zero (or the whole graph, if zero is not in the range) - for example, if you have something on the range [-5, 1], take [-5,0].
Figure out approximately how long this segment will be, in ticks. This is just dividing the length by the width of a tick. So suppose the method says that we can put 11 ticks in from -5 to 0. This is our upper bound. For the shorter side, we'll just mirror the result on the longer side.
Now try to put in as many (up to 11) ticks in, such that the marker for each tick in the form i*10*10^n, i*5*10^n, i*2*10^n, where n is an integer, and i is the index of the tick. Now it's an optimization problem - we want to maximize the number of ticks we can put in, while at the same time minimizing the distance between the last tick and the end of the result. So assign a score for getting as many ticks as we can, less than our upper bound, and assign a score to getting the last tick close to n - you'll have to experiment here.
In the above example, try n = 1. We get 1 tick (at i=0). n = 2 gives us 1 tick, and we're further from the lower bound, so we know that we have to go the other way. n = 0 gives us 6 ticks, at each integer point point. n = -1 gives us 12 ticks (0, -0.5, ..., -5.0). n = -2 gives us 24 ticks, and so on. The scoring algorithm will give them each a score - higher means a better method.
Do this again for the i * 5 * 10^n, and i*2*10^n, and take the one with the best score.
(as an example scoring algorithm, say that the score is the distance to the last tick times the maximum number of ticks minus the number needed. This will likely be bad, but it'll serve as a decent starting point).
Funnily enough, just over a week ago I came here looking for an answer to the same question, but went away again and decided to come up with my own algorithm. I am here to share, in case it is of any use.
I wrote the code in Python to try and bust out a solution as quickly as possible, but it can easily be ported to any other language.
The function below calculates the appropriate interval (which I have allowed to be either 10**n, 2*10**n, 4*10**n or 5*10**n) for a given range of data, and then calculates the locations at which to place the ticks (based on which numbers within the range are divisble by the interval). I have not used the modulo % operator, since it does not work properly with floating-point numbers due to floating-point arithmetic rounding errors.
Code:
import math
def get_tick_positions(data: list):
if len(data) == 0:
return []
retpoints = []
data_range = max(data) - min(data)
lower_bound = min(data) - data_range/10
upper_bound = max(data) + data_range/10
view_range = upper_bound - lower_bound
num = lower_bound
n = math.floor(math.log10(view_range) - 1)
interval = 10**n
num_ticks = 1
while num <= upper_bound:
num += interval
num_ticks += 1
if num_ticks > 10:
if interval == 10 ** n:
interval = 2 * 10 ** n
elif interval == 2 * 10 ** n:
interval = 4 * 10 ** n
elif interval == 4 * 10 ** n:
interval = 5 * 10 ** n
else:
n += 1
interval = 10 ** n
num = lower_bound
num_ticks = 1
if view_range >= 10:
copy_interval = interval
else:
if interval == 10 ** n:
copy_interval = 1
elif interval == 2 * 10 ** n:
copy_interval = 2
elif interval == 4 * 10 ** n:
copy_interval = 4
else:
copy_interval = 5
first_val = 0
prev_val = 0
times = 0
temp_log = math.log10(interval)
if math.isclose(lower_bound, 0):
first_val = 0
elif lower_bound < 0:
if upper_bound < -2*interval:
if n < 0:
copy_ub = round(upper_bound*10**(abs(temp_log) + 1))
times = copy_ub // round(interval*10**(abs(temp_log) + 1)) + 2
else:
times = upper_bound // round(interval) + 2
while first_val >= lower_bound:
prev_val = first_val
first_val = times * copy_interval
if n < 0:
first_val *= (10**n)
times -= 1
first_val = prev_val
times += 3
else:
if lower_bound > 2*interval:
if n < 0:
copy_ub = round(lower_bound*10**(abs(temp_log) + 1))
times = copy_ub // round(interval*10**(abs(temp_log) + 1)) - 2
else:
times = lower_bound // round(interval) - 2
while first_val < lower_bound:
first_val = times*copy_interval
if n < 0:
first_val *= (10**n)
times += 1
if n < 0:
retpoints.append(first_val)
else:
retpoints.append(round(first_val))
val = first_val
times = 1
while val <= upper_bound:
val = first_val + times * interval
if n < 0:
retpoints.append(val)
else:
retpoints.append(round(val))
times += 1
retpoints.pop()
return retpoints
When passing in the following three data-points to the function
points = [-0.00493, -0.0003892, -0.00003292]
... the output I get (as a list) is as follows:
[-0.005, -0.004, -0.003, -0.002, -0.001, 0.0]
When passing this:
points = [1.399, 38.23823, 8309.33, 112990.12]
... I get:
[0, 20000, 40000, 60000, 80000, 100000, 120000]
When passing this:
points = [-54, -32, -19, -17, -13, -11, -8, -4, 12, 15, 68]
... I get:
[-60, -40, -20, 0, 20, 40, 60, 80]
... which all seem to be a decent choice of positions for placing ticks.
The function is written to allow 5-10 ticks, but that could easily be changed if you so please.
Whether the list of data supplied contains ordered or unordered data it does not matter, since it is only the minimum and maximum data points within the list that matter.
This simple algorithm yields an interval that is multiple of 1, 2, or 5 times a power of 10. And the axis range gets divided in at least 5 intervals. The code sample is in java language:
protected double calculateInterval(double range) {
double x = Math.pow(10.0, Math.floor(Math.log10(range)));
if (range / x >= 5)
return x;
else if (range / (x / 2.0) >= 5)
return x / 2.0;
else
return x / 5.0;
}
This is an alternative, for minimum 10 intervals:
protected double calculateInterval(double range) {
double x = Math.pow(10.0, Math.floor(Math.log10(range)));
if (range / (x / 2.0) >= 10)
return x / 2.0;
else if (range / (x / 5.0) >= 10)
return x / 5.0;
else
return x / 10.0;
}
I've been using the jQuery flot graph library. It's open source and does axis/tick generation quite well. I'd suggest looking at it's code and pinching some ideas from there.

Resources