Force sum of weights in vector to be 100 - c++

I need to populate a vector so that it holds a sum of weights, where the sum must be 100. In other words, the number of items is equal to the divisor, and its values are the quotient, to ensure (force) the sum of the vector to equal 100.
Something like this: 100/3=3.333333...
vector[0]=33.33
vector[1]=33.34
vector[2]=33.33
The sum of this needs to be exactly 100 (some sort of selective rounding?)
Another example: 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
I've seen something like this done in grocery stores where something on sale might be 3 for $11, so the register displays the prices like 3.67, 3.66, and so on.
The values must add up to exactly 100 though I was thinking of doing this with an epsilon but that wouldn't work.
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
}
EDIT: The client wants the values stored (and displayed) in values fixed at two decimal places to visually see they add to 100.

Like the comments say, store money in terms of cents.
#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
When you divide 100 by 6, you get 16, with 4 leftover. This will put those 4 leftover in each of the first four slots of the vector. Proof of compilation: http://ideone.com/jrInai

There's no one "correct" way to do this. A place to start would be to add up the contents of the vector, and find the difference between 100 and that result you obtained. How you'd fold that in to the individual items would inherently be a heuristic. There are a couple of routes you could take:
Add the difference you found divided by the number of elements in the vector to each element in the vector. This has the advantage that it'll affect an individual value by the smallest amount possible in order to achieve your constraint.
You might want to just add the difference to the first or last element in the vector. This has the advantage that the fewest number of elements in the vector are modified.
You might want to list a separate rounding error element in the vector, which will just be the difference. This gives the most "correct" answer, but might not be what your users want.
Only you can decide what kind of heuristic to use based on the application you're building.
It should be noted that using floating point numbers (e.g. float, double, and long double) may result in errors when storing money values -- you should use fixed point decimal arithmetic for such calculations, because that's how money calculations are done in "the real world". Because floating point uses the base 2 number system internally (on most systems), there will be small rounding errors induced in the conversion from decimal to binary and back. You'll likely have no problem with small values, but if the dollar value is large you'll start seeing problems with the number of digits of precision available in a double.

You can divide into whatever is left as you go, subtracting the last value from the remaining amount.
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);
}

In your example,
100/6=16.67 (rounded)
Then you just multiply it by 6-1=5 and get 83.35
And now you know that in order to make the sum to be exactly 100, you need to make the price of the last element to be equal to
100 - 83.35 = 16.65

Related

Problem when i used some large large value i get wrong output with my function

So I'm new to stackoverflow and coding I was learning about functions in c++ and how the stack frame works etc..
in that I made a function for factorials and used that to calculate binomial coefficients. it worked fine for small values like n=10 and r=5 etc... but for large a medium value like 23C12 it gave 4 as answer.
IDK what is wrong with the code or I forgot to add something.
My code:
#include <iostream>
using namespace std;
int fact(int n)
{
int a = 1;
for (int i = 1; i <= n; i++)
{
a *= i;
}
return a;
}
int main()
{
int n, r;
cin >> n >> r;
if (n >= r)
{
int coeff = fact(n) / (fact(n - r) * fact(r));
cout << coeff << endl;
}
else
{
cout << "please enter valid values. i.e n>=r." << endl;
}
return 0;
}
Thanks for your help!
You're not doing anything "wrong" per se. It's just that factorials quicky become huge numbers.
In your example you're using ints, which are typically 32-bit variables. If you take a look at a table of factorials, you'll note that log2(13!) = 32.535.... So the largest factorial that will fit in a 32-bit number is 12!. For a 64-bit variable, the largest factorial you can store is 20! (since log2(21!) = 65.469...).
When you get 4 as the result that's because of overflow.
If you need to be able to calculate such huge numbers, I suggest a bignum library such as GMP.
Factorials overflow easily. In practice you rarely need bare factorials, but they almost always appear in fractions. In your case:
int coeff = fact(n) / (fact(n - r) * fact(r));
Note the the first min(n,n-r,r) factors of the denominator and numerator are identical. I am not going to provide you the code, but I hope an example will help to understand what to do instead.
Consider n=5, r=3 then coeff is
5*4*3*2*1 / 2*1 * 3*2*1
And before actually carrying out any calculations you can reduce that to
5*4 / 2*1
If you are certain that the final result coeff does fit in an int, you can also calculate it using ints. You just need to take care not to overflow the intermediate terms.

Sum of partial group of {𝑥^(0),𝑥(1),……,𝑥(𝑦)}

I want to write a program where input are x and y integer values
and then:
Let s be the set { x0, 𝑥1, …, 𝑥y}; store it in array.
Repeat:
Partition the set s into two subsets: s1 and s2.
Find the sum of each of the two subset and store them in variables like sum1, sum2.
Calculate the product of sum1 * sum2.
The program ends after passing all over the partial groups that could be formed and then prints the max value of the product sum1 * sum2.
example: suppose x=2 , y=3 s= {1,2,4,8} one of the divisions is to take s1 ={1,4} , s2={2,8} sum1=5 , sum2= 10 the product is 50 and that will be compared to other productd that were calculated in the same way like s1 ={1} , s2={2,4,8} sum1=1 , sum2=14 and the product is 14 and so on.
My code so far:
#include <iostream>
using namespace std;
int main ()
{
int a[10000]; // Max value expected.
int x;
int y;
cin >> x;
cin >> y;
int xexpy = 1;
int k;
for (int i = 0; i <= y; i++)
{
xexpy = 1;
k = i;
while(k > 0)
{
xexpy = xexpy * x;
k--;
}
cout << "\n" << xexpy;
a[i] = xexpy;
}
return 0;
}
This is not a programming problem, it is a combinatorics problem with a theoretical rather than an empirical approach to its solution. You can simply print the correct solution and not bother iterating over any partitions.
Why is that?
Let
i.e. z is the fraction of the sum of all s elements that's in s1. It holds that
and thus, the product of both sets satisfies:
As a function of z (not of x and y), this is a parabola that takes its maximum at z = 1/2; and there are no other local maximum points, i.e. getting closer to 1/2 necessarily increases that product. Thus what you want to do is partition the full set so that each of s1 and s2 are as close as possible to have half the sum of elements.
In general, you might have had to use programming to consider multiple subsets, but since your elements are given by a formula - and it's the formula of a geometric sequence.
First, let's assume x >= 2 and y >= 2, otherwise this is not an interesting problem.
Now, for x >= 2, we know that
(the sum of a geometric sequence), and thus
i.e. the last element always outweighs all other elements put together. That's why you always want to choose {xy} as s1 and as all other elements as s2. No need to run any program. You can then also easily calculate the optimum product-of-sums.
Note: If we don't make assumptions about the elements of s, except that they're non-negative integers, finding the optimum solution is an optimization version of the Partition problem - which is NP-complete. That means, very roughly, that there is no solution is fundamentally much more efficient than just trying all possible combinations.
Here's a cheesy all-combinations-of-supplied-arguments generator, provided without comment or explanation because I think this is homework, and the exercise of understanding how and why this does what it does is the point here.
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main(int c, const char **v)
{
basic_string<const char *> options(v);
auto N(options.length());
for (auto n = 1u; n < N; ++n) {
vector<char> pick(N);
fill_n(pick.rbegin(), n, 1);
do for (auto j=1u; j<N; ++j)
if (pick[j])
cout << options[j]<<' ';
while (cout<<'\n', next_permutation(begin(pick)+1, end(pick)));
}
}

Density of doubles between 2 given numbers

Important Edit: The original question was about getting the density of both doubles and fractions. As i get the answer for doubles and not for fractions, I'm changing the topic to close this question. The other half of the original question is here
New question
I want to find the density of doubles between 2 given numbers but I can't think of a good way. So I'm looking for a closed-form expressions doublesIn(a,b). Or some code that does the work in a reasonable time.
With doubles i should use some formula with mantissa and exponent I'm not aware of. I already have a code using nextafter and it's awfully slow close to [-1,1] (below 1e6 is very slow)
.
Any ideas? Thanks in advance! :)
PS: If you want to know, I'm coding some math stuff for myself and I want to find how useful would be to replace double with a fraction (long,long or similar) on certain algorithms (like Gaussian elimination, newton's method for finding roots, etc), and for that I want to have some measures.
In what follows, including the program, I am assuming double is represented by IEEE 754 64-bit binary floating point. That is the most likely case, but not guaranteed by the C++ standard.
You can count doubles in a range in constant time, because you can count unsigned integers in a range in constant time by subtracting the start from the end and adjusting for whether the range is open or closed.
The doubles in a finite non-negative range have bit patterns that form a consecutive sequence of integers. For example, the range [1.0,2.0] contains one double for each integer in the range [0x3ff0_0000_0000_0000, 0x4000_0000_0000_0000].
Finite non-positive ranges of doubles behave the same way except the unsigned bit patterns increase in value as the doubles become more negative.
If your range includes both positive and negative numbers, split it at zero, so that you deal with one non-negative range and another non-positive range.
Most of the complications arise when you want to get the count exactly right. In that case, you need to adjust for whether the range is open or closed, and to count zero exactly once.
For your purpose, being off by one or two in a few hundred million may not matter much.
Here is a simple program that demonstrates the idea. It has received little error checking, so use at your own risk.
#include <iostream>
#include <cmath>
using namespace std;
uint64_t count(double start, double end);
void testit(uint64_t expected, double start, double end) {
cout << hex << "Should be " << expected << ": " << count(start, end)
<< endl;
}
double increment(double data, int count) {
int i;
for (i = 0; i < count; i++) {
data = nextafter(data, INFINITY);
}
return data;
}
double decrement(double data, int count) {
int i;
for (i = 0; i < count; i++) {
data = nextafter(data, -INFINITY);
}
return data;
}
int main() {
testit((uint64_t) 1 << 52, 1.0, 2.0);
testit(5, 3.0, increment(3.0, 5));
testit(2, decrement(0, 1), increment(0, 1));
testit((uint64_t) 1 << 52, -2.0, -1.0);
testit(1, -0.0, increment(0, 1));
testit(10, decrement(0,10), -0.0);
return 0;
}
// Return the bit pattern representing a double as
// a 64-bit unsigned integer.
uint64_t toInteger(double data) {
return *reinterpret_cast<uint64_t *>(&data);
}
// Count the doubles in a range, assuming double
// is IEEE 754 64-bit binary.
// Counts [start,end), including start but excluding end
uint64_t count(double start, double end) {
if (!(isfinite(start) && isfinite(end) && start <= end)) {
// Insert real error handling here
cerr << "error" << endl;
return 0;
}
if (start < 0) {
if (end < 0) {
return count(fabs(end), fabs(start));
} else if (end == 0) {
return count(0, fabs(start));
} else {
return count(start, 0) + count(0, end);
}
}
if (start == -0.0) {
start = 0.0;
}
return toInteger(end) - toInteger(start);
}

C++ Finding the minimum quotient from two different integer arrays of the same size

I have 2 different arrays numerator[ ], and denominator[ ] and int size which is 9. They both consist of 9 different integers, and I need to find the lowest quotient of 2 ints
(the percentage - (numerator[ ])/(denominator[ ]) ) in the two arrays. How would I go about doing this?
Do you want to return the percentage or the quotient(with no remainder)?
Following code returns the percentage. Change double to int, if you want the quotient.
#include<limits>
double lowestQuotient(const int *numerator, const int *denominator)
{
double min=DBL_MAX;
double quotient;
for(i=0;i<9;i++)
{
if (denominator[i]==0)
continue;
quotient = (double)numerator [i]/denominator [i];
if (i==0 || quotient<min)
min=quotient;
}
return min;
}
Edit: This answer was written before the problem statement was changed to clarify that the intention was not to compare every combination, but instead to only take pair-wise quotients. That simplifies the problem quite a bit and makes my lengthy solution here overkill. This was also written before a solution involving floating point values was indicated; I assumed that the questioner was interested in the mathematical definition of the quotient of two integers, which is itself necessarily an integer. All the same I'll leave this here for posterity...
Edit 2: Fixed the compilation error -- thanks James Root for pointing out the error.
This is a math problem first and a programming problem second.
The naive implementation is to compute every combination of numerators from the first array divided by denominators from the second array, track the minimum quotient as we go, and compute the result.
This would look something like the following:
#include <climits>
#include <algorithm>
int minimum_quotient(int numerator[], int denominator[], int size)
{
int minimum = INT_MAX; // minimum quotient
for (int i = 0; i < size; ++i)
for (int j = 0; j < size; ++j)
if (denominator[j] != 0) // avoid division by 0
minimum = std::min(minimum, numerator[i] / denominator[j]);
return 0;
}
With size being a known, small number, this should be sufficient. However, if we are concerned about the case in which size becomes very large, we may want to avoid the above written solution, which scales proportionate to the square of the size of the input.
Here is an idea for a solution that scales better with larger sizes. Specifically it scales linearly with the size of the input. We can take advantage of the following facts:
If the numerators and denominators both have the same sign, then the smallest quotient will be from the numerator with the smallest absolute value and the denominator with the largest absolute value.
If the numerators and denominators have opposite signs, then the opposite is true: for the smallest quotient we want the numerator with the largest absolute value and the denominator with the smallest absolute value.
We can iterate through both lists once, accumulating the largest and smallest numerators and denominators, and then compare these at the end to find the smallest quotient:
#include <climits>
#include <algorithm>
int minimum_quotient(int numerator[], int denominator[], int size)
{
int min_num = INT_MAX, min_den = INT_MAX;
int max_num = INT_MIN, max_den = INT_MIN;
for (int i = 0; i < size; ++i)
{
min_num = std::min(min_num, numerator[i]);
max_num = std::max(max_num, numerator[i]);
min_den = std::min(min_den, denominator[i]);
max_den = std::max(max_den, denominator[i]);
}
int minimum = INT_MAX;
if (min_den != 0)
{
minimum = std::min(minimum, min_num / min_den);
minimum = std::min(minimum, max_num / min_den);
}
if (max_den != 0)
{
minimum = std::min(minimum, min_num / max_den);
minimum = std::min(minimum, max_num / max_den);
}
return minimum;
}

How to generate random double numbers with high precision in C++?

I am trying to generate a number of series of double random numbers with high precision. For example, 0.856365621 (has 9 digits after decimal).
I've found some methods from internet, however, they do generate double random number, but the precision is not as good as I request (only 6 digits after the decimal).
Thus, may I know how to achieve my goal?
In C++11 you can using the <random> header and in this specific example using std::uniform_real_distribution I am able to generate random numbers with more than 6 digits. In order to see set the number of digits that will be printed via std::cout we need to use std::setprecision:
#include <iostream>
#include <random>
#include <iomanip>
int main()
{
std::random_device rd;
std::mt19937 e2(rd());
std::uniform_real_distribution<> dist(1, 10);
for( int i = 0 ; i < 10; ++i )
{
std::cout << std::fixed << std::setprecision(10) << dist(e2) << std::endl ;
}
return 0 ;
}
you can use std::numeric_limits::digits10 to determine the precision available.
std::cout << std::numeric_limits<double>::digits10 << std::endl;
In a typical system, RAND_MAX is 231-1 or something similar to that. So your "precision" from using a method like:L
double r = rand()/RAND_MAX;
would be 1/(2<sup>31</sup)-1 - this should give you 8-9 digits "precision" in the random number. Make sure you print with high enough precision:
cout << r << endl;
will not do. This will work better:
cout << fixed << sprecision(15) << r << endl;
Of course, there are some systems out there with much smaller RAND_MAX, in which case the results may be less "precise" - however, you should still get digits down in the 9-12 range, just that they are more likely to be "samey".
Why not create your value out of multiple calls of the random function instead?
For instance:
const int numDecimals = 9;
double result = 0.0;
double div = 1.0;
double mul = 1.0;
for (int n = 0; n < numDecimals; ++n)
{
int t = rand() % 10;
result += t * mul;
mul *= 10.0;
div /= 10.0;
}
result = result * div;
I would personally try a new implementation of the rand function though or at least multiply with the current time or something..
In my case, I'm using MQL5, a very close derivative of C++ for a specific market, whose only random generator produces a random integer from 0 to 32767 (= (2^15)-1). Far too low precision.
So I've adapted his idea -- randomly generate a string of digits any length I want -- to solve my problem, more reliably (and arguably more randomly also), than anything else I can find or think of. My version builds a string and converts it to a double at the end -- avoids any potential math/rounding errors along the way (because we all know 0.1 + 0.2 != 0.3 😉 )
Posting it here in case it helps anyone.
(Disclaimer: The following is valid MQL5. MQL5 and C++ are very close, but some differences. eg. No RAND_MAX constant (so I've hard-coded the 32767). I'm not entirely sure of all the differences, so there may be C++ syntax errors here. Please adapt accordingly).
const int RAND_MAX_INCL = 32767;
const int RAND_MAX_EXCL = RAND_MAX_INCL + 1;
int iRandomDigit() {
const double dRand = rand()/RAND_MAX_EXCL; // double 0.0 <= dRand < 1.0
return (int)(dRand * 10); // int 0 <= result < 10
};
double dRandom0IncTo1Exc(const int iPrecisionDigits) {
int iPrecisionDigits2 = iPrecisionDigits;
if ( iPrecisionDigits > DBL_DIG ) { // DBL_DIG == "Number of significant decimal digits for double type"
Print("WARNING: Can't generate random number with precision > ", DBL_DIG, ". Adjusted precision to ", DBL_DIG, " accordingly.");
iPrecisionDigits2 = DBL_DIG;
};
string sDigits = "";
for (int i = 0; i < iPrecisionDigits2; i++) {
sDigits += (string)iRandomDigit();
};
const string sResult = "0." + sDigits;
const double dResult = StringToDouble(sResult);
return dResult;
}
Noted in a comment on #MasterPlanMan's answer -- the other answers use more "official" methods designed for the question, from standard library, etc. However, I think conceptually it's a good solution when faced with limitations that the other answers can't address.