IceFire IceFire - 3 months ago 17
C++ Question

distribute two integers according to ratio

Say, I have some integer n and would like to subdivide it into two other integers according to some ratio. I have some approach where I ask myself whether it does work or not.

For example: 20 with ratio 70% should be subdivided into 14,6.

The obvious solution would be:

int n = 20;
double ratio = .7;
int n1 = static_cast<int>(n * ratio);
int n2 = static_cast<int>(n * (1 - ratio));


Since the cast always
floor
s, however, I usually underrate my result. If I use
std::round
, there are still cases that are not working. For example, if the first decimal place is a 5, then both numbers will be rounded up.

Some colleagues suggested: Ceil the first number and floor the second one. In most of my tests, this works, however:

1) Does it really always work, also taking into accounting possible rounding errors that naturally occur in multiplying numbers? What I think of: 20*.7 could be 14, while 20*.3 could be 5.999999. So, my sum might be 14 + 5 = 19. This is just my guess, however, I do not know whether these kind of results can or cannot occur (otherwise the answer would be simply that this kind of rounding proposition does not work)

2) Even if it does work... Why?

(I have in mind that I could just calculate number 1 by n * ratio and calculate number 2 by n - n * ratio, but I would still be interested in the answer to this question)

Answer

Here is example that confirms your suspicion and shows that the ceil+floor method doesn't always work. It is caused by the finite precision of floating point numbers on computer:

#include <iostream>
#include <cmath>

int main() {
    int n = 10;
    double ratio = 0.7;
    int n1 = static_cast<int>(floor(n * ratio));
    int n2 = static_cast<int>(ceil(n * (1.0 - ratio)));

    std::cout << n1 << " " << n2 << std::endl;
}

Output:

7 4

7 + 4 is 11, so it's wrong.