I have been trying to learn C++ from a C# background, and I am running in to a very weird mistake in my Maximum Pair Product method.
The method works as expected with small numbers. For products of large numbers it produces a strange rounding and outputs the incorrect output.
int64_t Testing::MaximumPairProductFast(const std::vector<int>& numbers)
{
int64_t largestIntA = 0;
int64_t largestIntB = 0;
for (int i = 0; i < numbers.size(); i++)
{
// find first largest number
if (numbers[i] > largestIntA) largestIntA = numbers[i];
}
for (int i = 0; i < numbers.size(); i++)
{
//find second largest number
if (numbers[i] > largestIntB && numbers[i]!= largestIntA) largestIntB = numbers[i];
}
return largestIntA * largestIntB;
}
The main program
int main()
{
Testing ch;
std::vector<int> test{ 100000,90000 };
int result= ch.MaximumPairProductFast(test);
std::cout << result << "\n";
}
The output of the computation will be 410065408 instead of 9000000000 which is the correct answer
The weird thing is when I try to print this:
std::cout << (int64_t) 100000 * 90000 << "\n";
It does give the correct result 9000000000.
But if I don't cast it to int64_t :
std::cout << 100000 * 90000 << "\n";
The result is 410065408, which is exactly the output from my method even though I have ensured to return an int64_t type.
I have also tried this, but the outcome is the same:
int64_t Test::MaximumPairProductFast(const std::vector<int>& numbers)
{
int64_t largestIntA = 0;
int64_t largestIntB = 0;
for (int i = 0; i < numbers.size(); i++)
{
// find first largest number
if ((int64_t) numbers[i] > largestIntA) largestIntA = (int64_t) numbers[i];
}
for (int i = 0; i < numbers.size(); i++)
{
//find second largest number
if ((int64_t) numbers[i] > largestIntB && (int64_t) numbers[i]!= largestIntA) largestIntB = (int64_t) numbers[i];
}
return largestIntA * largestIntB;
}
Am I missing an obvious detail?
You are truncating your result from a int64_t to an int. On a typical system these days, you'll truncate a 64 bit integer and store it in a 32 bit value.
If you compile with the warning level increased, the compiler will tell you about this problem.
The solution is to declare result with the proper type:
int64_t result = ch.MaximumPairProductFast(test);
Or, just let the compiler use the correct type with auto:
auto result = ch.MaximumPairProductFast(test);
In your second example, the constants 100000 and 90000 are integers, so the multiplication of them will be done as integers. When you case one of the values to int64_t, the multiplication will be done with 64 bit ints. This can also be expressed with 100000LL.
On your system int is a 32-bit integer. int64_t is 64-bit integer. The problem in your code is you are multiplying two 32-bit ints so you're getting a 32-bit int result. Your answer is overflowing. When you explicitly cast it to int64_t, the operands are now 64-bit ints and you're getting a 64-bit int result which can hold the large value and not overflow.
I'll suggest you either:
use std::vector<int64_t> instead of std::vector<int>
If you're worried about space, do as you did, explicitely cast it to 64-bit int and then multiply
Related
The below given code is not working for high value (eg: 51574523448, 1000000000000, etc) even after using long long and giving some different different values but is properly working for low values.
Can anyone explain what is the problem and how to solve it. (Sorry for weak english).
int repeatedString(string s, long n) {
long count = 0;
int secondCount = 0;
long num;
int length = s.length();
double remainder;
num = (long) n / (length);
remainder = n % (length);
for(int i=0; i < length; i++) {
if(s[i]=='a') {
count++;
if(i < remainder)
secondCount++;
}
}
count = count*num + secondCount;
return count;
}
Try running this program on your platform:
#include <iostream>
#include <limits>
int main()
{
std::cout << std::numeric_limits<long>::max() << '\n';
}
The number it prints is the maximum value a long can store. I get 2147483647, which is much less than 51574523448. You will likely need to use a larger data type, such as long long.
I've written a program, which shows binary representation of a particular integer value, using bitwise operators in C++. For even numbers it works as I expect, but for odd it adds 1 to the left of the binary representation.
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
int main()
{
unsigned int a = 128;
for (int i = sizeof(a) * 8; i >= 0; --i) {
if (a & (1UL << i)) { // if i-th digit is 1
cout << 1; // Output 1
}
else {
cout << 0; // Otherwise output 0
}
}
cout << endl;
system("pause");
return 0;
}
Results:
For a = 128: 000000000000000000000000010000000,
For a = 127: 100000000000000000000000001111111
You might prefer CHAR_BIT macro instead of raw 8 (#include <climits>).
Consider your start value! Assuming unsigned int having 32 bit, your start value is int i = 4*8, so 1U << i shifts the value out of range. This is undefined behaviour and could result in anything, obviously, your specific compiler or hardware shifts %32, thus you get an initial value & 1, resulting in the unexpected leading 1... Did you notice that you actually printed out 33 digits instead of only 32?
The problem is here:
for (int i = sizeof(a) * 8; i >= 0; --i) {
it should be:
for (int i = sizeof(a) * 8; i-- ; ) {
http://coliru.stacked-crooked.com/a/8cb2b745063883fa
In the C++ function below, why is numbers[max_index1] cast to long long and then multiplied by numbers[max_index2]? I would of thought that you'd multiply the numbers and then cast?
Also would it not make more sense to make the vector numbers type long long instead of int therefore the casting wouldn't be necessary?
long long MaxPairwiseProductFast(const vector<int>& numbers) {
int n = numbers.size();
int max_index1 = -1;
cout << "value at max_index1 is " << numbers[max_index1] << std::endl;
for(int i = 0; i < n; i++)
if((max_index1 == -1) || (numbers[i] > numbers[max_index1]))
max_index1 = i;
int max_index2 = -1;
for(int j = 0; j < n; j++)
if((numbers[j] != numbers[max_index1]) && ((max_index2 == -1) || (numbers[j] > numbers[max_index2])))
max_index2 = j;
return ((long long)(numbers[max_index1])) * numbers[max_index2];
}
int main() {
int n;
cin >> n;
vector<int> numbers(n);
for (int i = 0; i < n; ++i) {
cin >> numbers[i];
}
long long result = MaxPairwiseProductFast(numbers);
cout << result << "\n";
return 0;
}
((long long)(numbers[max_index1])) * numbers[max_index2];
numbers[max_index2] will be promoted to long long before multiplication is performed.
If you multiply two int's and the result overflowed, there is nothing you can achieve by casting that result to long long, so you cast first, then multiply.
Also would be not make more sense to make the vector numbers type long long instead of int therefore the casting wouldn't be necessary?
If you know that the individual numbers will fit an int, but the result of multiplying two int's can overflow, this will help save space.
I woudld of thought that you'd multiply the numbers and then cast?
Imagine your two operands have the value std::numeric_limits<int>::max(). This is the biggest value an int can represent, and (since it's a positive integer) the result of squaring this number is even bigger.
When you multiply two int values, the result is also an int. See here (specifically conversions, integral promotion and overflow of signed types).
Since the result is by definition bigger than the largest value you can store in an int, doing this multiplication with ints gives an undefined result. You need to perform the multiplication with a type large enough to store the result.
I am trying to solve a question in which i need to find out the number of possible ways to make a team of two members.(note: a team can have at most two person)
After making this code, It works properly but in some test cases it shows floating point error ad i can't find out what it is exactly.
Input: 1st line : Number of test cases
2nd line: number of total person
Thank you
#include<iostream>
using namespace std;
long C(long n, long r)
{
long f[n + 1];
f[0] = 1;
for (long i = 1; i <= n; i++)
{
f[i] = i * f[i - 1];
}
return f[n] / f[r] / f[n - r];
}
int main()
{
long n, r, m,t;
cin>>t;
while(t--)
{
cin>>n;
r=1;
cout<<C(n, min(r, n - r))+1<<endl;
}
return 0;
}
You aren't getting a floating point exception. You are getting a divide by zero exception. Because your code is attempting to divide by the number 0 (which can't be done on a computer).
When you invoke C(100, 1) the main loop that initializes the f array inside C increases exponentially. Eventually, two values are multiplied such that i * f[i-1] is zero due to overflow. That leads to all the subsequent f[i] values being initialized to zero. And then the division that follows the loop is a division by zero.
Although purists on these forums will say this is undefined, here's what's really happening on most 2's complement architectures. Or at least on my computer....
At i==21:
f[20] is already equal to 2432902008176640000
21 * 2432902008176640000 overflows for 64-bit signed, and will typically become -4249290049419214848 So at this point, your program is bugged and is now in undefined behavior.
At i==66
f[65] is equal to 0x8000000000000000. So 66 * f[65] gets calculated as zero for reasons that make sense to me, but should be understood as undefined behavior.
With f[66] assigned to 0, all subsequent assignments of f[i] become zero as well. After the main loop inside C is over, the f[n-r] is zero. Hence, divide by zero error.
Update
I went back and reverse engineered your problem. It seems like your C function is just trying to compute this expression:
N!
-------------
R! * (N-R)!
Which is the "number of unique sorted combinations"
In which case instead of computing the large factorial of N!, we can reduce that expression to this:
n
[ ∏ i ]
n-r
--------------------
R!
This won't eliminate overflow, but will allow your C function to be able to take on larger values of N and R to compute the number of combinations without error.
But we can also take advantage of simple reduction before trying to do a big long factorial expression
For example, let's say we were trying to compute C(15,5). Mathematically that is:
15!
--------
10! 5!
Or as we expressed above:
1*2*3*4*5*6*7*8*9*10*11*12*13*14*15
-----------------------------------
1*2*3*4*5*6*7*8*9*10 * 1*2*3*4*5
The first 10 factors of the numerator and denominator cancel each other out:
11*12*13*14*15
-----------------------------------
1*2*3*4*5
But intuitively, you can see that "12" in the numerator is already evenly divisible by denominators 2 and 3. And that 15 in the numerator is evenly divisible by 5 in the denominator. So simple reduction can be applied:
11*2*13*14*3
-----------------------------------
1 * 4
There's even more room for greatest common divisor reduction, but this is a great start.
Let's start with a helper function that computes the product of all the values in a list.
long long multiply_vector(std::vector<int>& values)
{
long long result = 1;
for (long i : values)
{
result = result * i;
if (result < 0)
{
std::cout << "ERROR - multiply_range hit overflow" << std::endl;
return 0;
}
}
return result;
}
Not let's implement C as using the above function after doing the reduction operation
long long C(int n, int r)
{
if ((r >= n) || (n < 0) || (r < 0))
{
std::cout << "invalid parameters passed to C" << std::endl;
return 0;
}
// compute
// n!
// -------------
// r! * (n-r)!
//
// assume (r < n)
// Which maps to
// n
// [∏ i]
// n - r
// --------------------
// R!
int end = n;
int start = n - r + 1;
std::vector<int> numerators;
std::vector<int> denominators;
long long numerator = 1;
long long denominator = 1;
for (int i = start; i <= end; i++)
{
numerators.push_back(i);
}
for (int i = 2; i <= r; i++)
{
denominators.push_back(i);
}
size_t n_length = numerators.size();
size_t d_length = denominators.size();
for (size_t n = 0; n < n_length; n++)
{
int nval = numerators[n];
for (size_t d = 0; d < d_length; d++)
{
int dval = denominators[d];
if ((nval % dval) == 0)
{
denominators[d] = 1;
numerators[n] = nval / dval;
}
}
}
numerator = multiply_vector(numerators);
denominator = multiply_vector(denominators);
if ((numerator == 0) || (denominator == 0))
{
std::cout << "Giving up. Can't resolve overflow" << std::endl;
return 0;
}
long long result = numerator / denominator;
return result;
}
You are not using floating-point. And you seem to be using variable sized arrays, which is a C feature and possibly a C++ extension but not standard.
Anyway, you will get overflow and therefore undefined behaviour even for rather small values of n.
In practice the overflow will lead to array elements becoming zero for not much larger values of n.
Your code will then divide by zero and crash.
They also might have a test case like (1000000000, 999999999) which is trivial to solve, but not for your code which I bet will crash.
You don't specify what you mean by "floating point error" - I reckon you are referring to the fact that you are doing an integer division rather than a floating point one so that you will always get integers rather than floats.
int a, b;
a = 7;
b = 2;
std::cout << a / b << std::endl;
this will result in 3, not 3.5! If you want floating point result you should use floats instead like this:
float a, b;
a = 7;
b = 2;
std::cout << a / b << std::end;
So the solution to your problem would simply be to use float instead of long long int.
Note also that you are using variable sized arrays which won't work in C++ - why not use std::vector instead??
Array syntax as:
type name[size]
Note: size must a constant not a variable
Example #1:
int name[10];
Example #2:
const int asize = 10;
int name[asize];
As part of my master thesis, I get a number (e.g. 5 bits) with 2 significant bits (2nd and 4th). This means for example x1x0x, where $x \in {0,1}$ (x could be 0 or 1) and 1,0 are bits with fixed values.
My first task is to compute all the combinations of the above given number , 2^3 = 8. This is called S_1 group.
Then I need to compute 'S_2' group and this is all the combinations of the two numbers x0x0x and x1x1x(this means one mismatch in the significant bits), this should give us $\bin{2}{1} * 2^3 = 2 * 2^3 = 16.
EDIT
Each number, x1x1x and x0x0x, is different from the Original number, x1x0x, at one significant bit.
Last group, S_3, is of course two mismatches from the significant bits, this means, all the numbers which pass the form x0x1x, 8 possibilities.
The computation could be computed recursively or independently, that is not a problem.
I would be happy if someone could give a starting point for these computations, since what I have is not so efficient.
EDIT
Maybe I chose my words wrongly, using significant bits. What I meant to say is that a specific places in a five bits number the bit are fixed. Those places I defined as specific bits.
EDIT
I saw already 2 answers and it seems I should have been clearer. What I am more interested in, is finding the numbers x0x0x, x1x1x and x0x1x with respect that this is a simply example. In reality, the group S_1 (in this example x1x0x) would be built with at least 12 bit long numbers and could contain 11 significant bits. Then I would have 12 groups...
If something is still not clear please ask ;)
#include <vector>
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
string format = "x1x0x";
unsigned int sigBits = 0;
unsigned int sigMask = 0;
unsigned int numSigBits = 0;
for (unsigned int i = 0; i < format.length(); ++i)
{
sigBits <<= 1;
sigMask <<= 1;
if (format[i] != 'x')
{
sigBits |= (format[i] - '0');
sigMask |= 1;
++numSigBits;
}
}
unsigned int numBits = format.length();
unsigned int maxNum = (1 << numBits);
vector<vector<unsigned int> > S;
for (unsigned int i = 0; i <= numSigBits; i++)
S.push_back(vector<unsigned int>());
for (unsigned int i = 0; i < maxNum; ++i)
{
unsigned int changedBits = (i & sigMask) ^ sigBits;
unsigned int distance = 0;
for (unsigned int j = 0; j < numBits; j++)
{
if (changedBits & 0x01)
++distance;
changedBits >>= 1;
}
S[distance].push_back(i);
}
for (unsigned int i = 0; i <= numSigBits; ++i)
{
cout << dec << "Set with distance " << i << endl;
vector<unsigned int>::iterator iter = S[i].begin();
while (iter != S[i].end())
{
cout << hex << showbase << *iter << endl;
++iter;
}
cout << endl;
}
return 0;
}
sigMask has a 1 where all your specific bits are. sigBits has a 1 wherever your specific bits are 1. changedBits has a 1 wherever the current value of i is different from sigBits. distance counts the number of bits that have changed. This is about as efficient as you can get without precomputing a lookup table for the distance calculation.
Of course, it doesn't actually matter what the fixed-bit values are, only that they're fixed. xyxyx, where y is fixed and x isn't, will always yield 8 potentials. The potential combinations of the two groups where y varies between them will always be a simple multiplication- that is, for each state that the first may be in, the second may be in each state.
Use bit logic.
//x1x1x
if(01010 AND test_byte) == 01010) //--> implies that the position where 1s are are 1.
There's probably a number-theoretic solution, but, this is very simple.
This needs to be done with a fixed-bit integer type. Some dynamic languages (python for example), will extend bits out if they think it's a good idea.
This is not hard, but it is time consuming, and TDD would be particularly appropriate here.