1
$\begingroup$

I'm developing a C++ program and I need to find a formula that given a number to reduce and a limit number, get a value between 0 and this limit number.

I don't know if it is allow to put C++ code here, but I want to show you my function:

double Utils::reduceNumber(double numberToReduce, double limitNumber)
{
    double factor = 0.0;
    double result = 0.0;

    factor = std::abs(numberToReduce / limitNumber);

    if (factor != (int)factor)
        factor = (int)factor + 1;

    if (numberToReduce > 0)
        result = numberToReduce - (byNumber * factor);
    else
        result = numberToReduce + (byNumber * factor);

    return result;
}

For example, If I want to reduce −465.986246 in a limit between 0 and 24, I have to do this:

−465.986246 + (24 x  20) = 14.013754

What is the formula to obtain that 20?

$\endgroup$
  • $\begingroup$ Try setting your factor as: $\frac{l - 2n}{2l}$ where $l$ is your limit and $n$ is the number you are "reducing" to the interval $(0,l)$. $\endgroup$ – anakhro Jul 31 '15 at 16:38
  • $\begingroup$ Are you asking for a mathematical formula or one in C++? $\endgroup$ – Rory Daulton Jul 31 '15 at 16:43
  • $\begingroup$ I'm asking for a mathematical formula. I'm going to translate it to C++ later. $\endgroup$ – VansFannel Jul 31 '15 at 16:43
2
$\begingroup$

Let $a$ be a given number. Also, suppose that the limit is between $0$ and $N$.

If you want an integer $b$ such that $$0\le a+Nb\le N\iff -\frac{a}{N}\le b\le \frac{N-a}{N},$$ then $$b=\left\lfloor\frac{N-a}{N}\right\rfloor$$ works where $\lfloor x\rfloor$ is the largest integer not greater than $x$.

For $a=−465.986246$ and $N=24$, we have $b=\left\lfloor\frac{24-(−465.986246)}{24}\right\rfloor=20$.

$\endgroup$
  • $\begingroup$ Thanks for your great answer. Now, a = 28.668119326367531 and I'm having problems because the b value is rounded to 0. $\endgroup$ – VansFannel Jul 31 '15 at 17:06
  • $\begingroup$ @VansFannel: For $a=28.668119326367531$ and $N=24$, I think $b=-1$. $\endgroup$ – mathlove Jul 31 '15 at 17:22
  • $\begingroup$ Thanks. Now I need that the value will be between 1 and N. How can I do it? $\endgroup$ – VansFannel Jan 26 '16 at 18:01
1
$\begingroup$

Just setting up some notation:

For your limit number $l > 0$ and the number you want to "reduce", $n$, you want to find another number $x$ such that it satisfies: $$(n + l\cdot x) \in (0,l).$$

So for example, we know that $\frac{l}{2} \in (0,l)$ obviously, so we will say you want to satisfy the equation: $$n + l\cdot x = \frac{l}{2}.$$

Solving this equation for $x$ results in the following: $$x = \frac{l-2n}{2l}.$$


Note this will always put the number in the centre of the interval $(0,l)$. You can also do this for other specific points in the interval $(0,l)$.

If you want some sort of random noise to not make it the exact centre of the interval each time, you can just let $\epsilon$ be your randomly generated number in the interval $(-1,1)$ and then set your $x$ as follows: $$x = \frac{l(1+\epsilon) - 2n}{2l}.$$

EDIT: I see that mathlove assumed you wanted an integer, so this solution likely isn't what you wanted (however you specify the 'factor' is a double in your code, so you might want to optimize that if that is the case...).

$\endgroup$
  • $\begingroup$ I need an integer, but I have to round factor's value because now I having problems when the number is 28.668119326367531. $\endgroup$ – VansFannel Jul 31 '15 at 17:05
  • 1
    $\begingroup$ @VansFannel Use mathlove's solution for an integer value. $\endgroup$ – anakhro Jul 31 '15 at 17:12
0
$\begingroup$

Using math love's solution, this is my function now:

double Utils::reduceNumber(double numberToReduce, double limitNumber)
{
    float factor = 0.0;
    double result = 0.0;

    factor = (limitNumber - numberToReduce) / limitNumber;

    if (factor < 0.0)
    {
        factor -= 1;
    }
    else
    {
        if ((std::abs(factor) - (int)std::abs(factor)) > 0.5)
        {
            factor += 1;
        }
    }

    result = numberToReduce + (byNumber * (int)factor);

    return result;
}

Now it works with 28.668119326367531 and with −465.986246 numbers.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.