2
$\begingroup$

I'm developing a software that has to round value to 50 or 100. In other words, the only allowed values are 0, 50, 100, 150, 200, 250, ...

I want to round a value in this way: if the value is 25 it rounds to 50, but if it is 24, it rounds to 0. The same with 75 rounds to 100, and 74 rounds to 50. And so on.

In other words, [0, 25), rounds to 0. [25, 50], it rounds to 50.

Given $x$ as the input value, I'm using this calculations:

  1. $x= x/100.0$
  2. Then, I rounds $x$ towards zero, truncating the fractional part (sorry, I don't know if there is a mathematical symbol for Truncate).
  3. $x=x*100.0$
  4. $x=x+50.0$

With these calculations, when $x=804.072$ it returns $850.0$, but it should returns $800.0$.

How can I fix this error?

$\endgroup$
3
  • 2
    $\begingroup$ Why do you add $50$ at the end? More broadly, since you are interested in multiples of $50$, you should divide by $50$, not $100$. $\endgroup$
    – lulu
    May 6 at 10:12
  • $\begingroup$ @lulu I don't know. I've been testing, and this is my best approach. Thank you. $\endgroup$
    – VansFannel
    May 6 at 12:41
  • $\begingroup$ Watch out for floating point errors. $\endgroup$
    – qwr
    May 7 at 3:02

3 Answers 3

4
$\begingroup$

Following the steps of your example, you get $$ 804.072 \quad \rightarrow \quad 8.04072 \quad \rightarrow \quad 8 \quad \rightarrow \quad 800 \quad \rightarrow \quad 850 $$ so of course you get 850. There's no point in arbitrarily adding 50 in the end.

Notice that you don't have to divide by 100. You can divide by 50 instead. Then, you'd get $$ 804.072 \quad \rightarrow (\text{divide by 50}) \rightarrow \quad 16.08144 \quad \rightarrow \quad 16 \quad \rightarrow (\text{multiply by 50}) \rightarrow \quad 800 $$ Notice that truncating rounds downwards so 799 would round to 750. Is that what you want?

$\endgroup$
1
  • $\begingroup$ Thank you. This is what I want, if value is in range [0, 25), it rounds to 0. If the value is in range [25, 50], it rounds to 50. $\endgroup$
    – VansFannel
    May 6 at 12:39
3
$\begingroup$

You want to have the following mapping:

$$ [25, 75) \to 50 $$ $$ [75, 125) \to 100 $$ $$\vdots$$

In general: $$ [50\cdot k - 25, 50 \cdot k + 25) \to 50 \cdot k \hspace{10pt} k \in \mathbb{Z} $$ Let's consider $n$ satisfying: $$50\cdot k - 25 \leqslant n < 50 \cdot k + 25$$ Thus we can modify this inequality a little bit to obtain: $$50\cdot k \leqslant n + 25 < 50 \cdot k + 50$$ $$k \leqslant \frac{ n + 25}{50} < k + 1$$ We can see that performing floor function (in other words truncating fractional part) on the expression involving $n$ will give us the exact value of $k$. $$ k = \left\lfloor\frac{ n + 25}{50}\right\rfloor $$ And thus demanded answer is: $$ \left\lfloor\frac{ n + 25}{50}\right\rfloor \cdot 50 $$

$\endgroup$
1
  • $\begingroup$ similarly, to round up, when only the floor/truncate function is available, one could use $ \lfloor (n+49)/50 \rfloor $ (or 49.999... up to the precision available. it's easier with integers) $\endgroup$
    – ilkkachu
    May 6 at 12:45
1
$\begingroup$

The target output set is 0, 50, 100, 150, ...

Integer rounding (nearest integer, floor, ceiling, etc) would typically give some continuous range of integers as output, e.g. 0, 1, 2, 3, ...

The simplest approach would be just to map those one-to-one, so we'd need to multiply by 50 to convert the output of integer rounding to the output we want.

Since we're multiplying by 50, we should first divide by 50 to reverse that, so we maintain the same scale.

Let's see what happens with an example of a boundary:

  • We want 24 to round to 0 and 25 to round to 1 (which will get multiplied by 50 to give 0 and 50 respectively).
  • If we start off dividing by 50, we get $\frac{24}{50} = 0.48$ and $\frac{25}{50} = 0.5$
  • To get the result we want, that's just the standard nearest-integer half-up rounding, and the end result would be just $50 \cdot round(\frac{x}{50})$.
  • If you want to use floor or truncate, you'd need to get $\frac{24}{50}$ to something that would floor to 0, and $\frac{25}{50}$ to something that would floor to 1. $\frac{49}{50}$ and $\frac{50}{50}$ is the point where that happens, and we can get there by just adding 25 before dividing, i.e. $50 \cdot floor(\frac{x+25}{50})$

The same idea above would also work for 24.999..., and one could verify this with other boundaries, or generalise the reasoning here, like another answer has done.

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .