按比例分配两个整数

时间:2016-09-01 13:31:26

标签: c++

说,我有一些整数n,并希望根据某种比例将其细分为另外两个整数。我有一些方法,我问自己它是否有效。

例如:20%与70%的比例应细分为14,6。

显而易见的解决方案是:

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

然而,由于演员总是floor,我通常会低估我的结果。如果我使用std::round,仍有一些情况无效。例如,如果第一个小数位是5,则两个数字都将向上舍入。

有些同事建议:Ceil是第一个,第二个是第二个。在我的大多数测试中,这都有效:

1)它是否真的一直有效,还考虑到在乘法数字中自然出现的可能的舍入误差?我的想法:20 * .7可能是14,而20 * .3可能是5.999999。所以,我的总和可能是14 + 5 = 19.这只是我的猜测,但是,我不知道这些结果是否可以发生(否则答案就是这种舍入命题不起作用)

2)即使它确实有效......为什么?

(我记得我可以用n *比率计算数字1并用n - n *比率计算数字2,但我仍然对这个问题的答案感兴趣)

3 个答案:

答案 0 :(得分:2)

这个怎么样?

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

答案 1 :(得分:1)

以下示例证实了您的怀疑,并表明ceil + floor方法并不总是有效。它是由计算机上浮点数的有限精度引起的:

#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;
}

输出:

7 4

7 + 4是11,所以它错了。

答案 2 :(得分:0)

你的解决方案并不总是有效,比率为77%,你会得到15和4(See on coliru)。

欢迎来到数值分析领域。

首先,您的计算机无法始终完美地存储浮动数字。正如您在示例中所看到的,.77存储为0.77000000000000001776(这是一个以2的幂的总和来表示数字的方法。)

进行浮点计算时,总是会有精度损失。您可以使用std::numeric_limits<double>::epsilon()获得此精度。

此外,从浮点数转换为整数时,您仍然会获得更多的精度损失,在您的情况下,差异足以让您得到不连贯的结果。

@ToniBig提供的解决方案和你的最后一句话具有“隐藏”这种损失并保持连贯数据的优势。