0

我需要填充一个向量,使其包含权重总和,其中总和必须为 100。换句话说,项目数等于除数,其值是商,以确保(强制)总和的向量等于 100。

像这样:100/3=3.333333...

vector[0]=33.33
vector[1]=33.34
vector[2]=33.33

总和必须正好是 100(某种选择性舍入?)另一个例子:100/6 = 16.66666667

vector[0]=16.67
vector[1]=16.67
vector[2]=16.66
vector[3]=16.67
vector[4]=16.67
vector[5]=16.66

我曾在杂货店看到过类似的情况,其中的商品售价可能是 11 美元 3 件,因此收银机显示的价格为 3.67、3.66 等。

这些值加起来必须正好是 100,尽管我想用 epsilon 来做这件事,但那是行不通的。

const int divisor = 6;
const int dividend = 10;

std::vector<double> myVec;
myVec.resize(6);

for (int i = 0; i < divisor; ++i)
{
    ...some magic that I don't know how to do
}

编辑:客户希望以固定在小数点后两位的值存储(和显示)的值,以直观地看到它们加到 100。

4

4 回答 4

4

就像评论说的那样,以美分存储钱。

#include <vector>
#include <iostream>
#include <iomanip>

std::vector<int> function(int divisor, int total) {
    std::vector<int> myVec(divisor);
    for (int i = 0; i < divisor; ++i) {
        myVec[i] = total/divisor; //rounding down
        if (i < total%divisor) //for each leftover
           myVec[i] += 1; //add one of the leftovers
    }
    return myVec;
}

void print_dollars(int cents) {
    std::cout << (cents/100) << '.';
    std::cout << std::setw(2) << std::setfill('0') << (cents%100) << ' ';
}

int main() {
   std::vector<int> r = function(6, 10000);
   int sum=0;
   for(int i=0; i<r.size(); ++i) {
       print_dollars(r[i]);
       sum += r[i];
   }
   std::cout << '\n';
   print_dollars(sum);
}
//16.67 16.67 16.67 16.67 16.66 16.66 
//100.00

当你将 100 除以 6 时,你得到 16,剩下 4 个。这会将剩下的 4 个放在向量的前四个插槽中。编译证明:http: //ideone.com/jrInai

于 2012-10-24T00:52:08.070 回答
2

没有一种“正确”的方法可以做到这一点。一个开始的地方是将向量的内容相加,并找出 100 与您获得的结果之间的差异。您如何将其折叠到单个项目中本质上是一种启发式方法。您可以采取以下几种路线:

  1. 将您找到的差除以向量中的元素数添加到向量中的每个元素。这样做的好处是,它会以尽可能小的方式影响单个值,以实现您的约束。
  2. 您可能只想将差异添加到向量中的第一个或最后一个元素。这样做的好处是修改了向量中最少数量的元素。
  3. 您可能希望在向量中列出一个单独的舍入误差元素,这就是区别。这给出了最“正确”的答案,但可能不是您的用户想要的。

只有您可以根据您正在构建的应用程序决定使用哪种启发式方法。

应该注意的是,在存储货币值时使用浮点数(例如floatdoublelong double)可能会导致错误——您应该使用定点十进制算法进行此类计算,因为这就是“现实世界”中货币计算的方式。因为浮点在内部(在大多数系统上)使用以 2 为底的数字系统,所以在从十进制到二进制再转换回来时会产生小的舍入误差。您可能对较小的值没有问题,但如果美元值较大,您将开始看到 double 中可用精度位数的问题。

于 2012-10-24T00:52:11.877 回答
1

你可以在你去的时候分成任何剩余的东西,从剩余的数量中减去最后一个值。

const int divisor = 6;
const int dividend = 10;

std::vector<double> myVec;
myVec.reserve(6);
double remain = 100.0;

for (int i = divisor; i >= 1; --i)
{
    double val = remain / (double)i;
    remain -= val;
    myVec.push_back(val);
}
于 2012-10-24T00:51:49.170 回答
0

在您的示例中,100/6=16.67(四舍五入)然后您只需将其乘以 6-1=5 并得到 83.35

现在您知道,为了使总和恰好为 100,您需要使最后一个元素的价格等于 100 - 83.35 = 16.65

于 2012-10-24T00:51:59.457 回答