Operator Overloading (int as bool) - c++

I'm trying to write a code that returns 1s and 0s instead of true or false. But this doesn't seem to be right.
int Short_Vector::operator==(const Short_Vector& obj){
if(a == obj.a && b == obj.b && c == obj.c && d == obj.d){
return 1;
}else{
return 0;
}
}
So it should return a value for each variable.
I also tried this:
int Short_Vector::operator==(const Short_Vector& obj){
int a_tf, b_tf, c_tf, d_tf;
if(a == obj.a){
a_tf = 1;
}else{
a_tf = 0;
}
if(b == obj.b){
b_tf = 1;
}else{
b_tf = 0;
}
if(c == obj.c){
c_tf = 1;
}else{
c_tf = 0;
}
if(d == obj.d){
d_tf = 1;
}else{
d_tf = 0;
}
return(a_tf, b_tf, c_tf, d_tf)
}
But I got an error about the commas being an operator.
EDIT
Getting the error: error: conversion from 'int' to non-scalar type 'Short_Vector.
I'm trying to represent a vector that looks like this [9,1,5,5].
Then i'll say
`Short_Vector a(2, 6, 9, 4);
Short_Vector b(3, 8, 7, 6);
Short_Vector c = a == b;
cout<<c;`
Output is then: [0,0,0,0]

The second method can't work because the return type is an 'int' and '(a_tf, b_tf, c_tf, d_tf)' is not an int but 4 ints separated by commas.
Since you want to return 4 booleans you could do the following:
int Short_Vector::operator==(const Short_Vector& obj)
{
//...
return (a_tf) | (b_tf << 1) | (c_tf << 2) | (d_tf << 3);
}
//the caller would do the follwoing:
int result = (MyObject1 == MyObject2);
if(result & (1 << 1) //b_tf is set to 1;
{
}
if(result & (1 << 3) //d_tf is set to 1;
{
}

You can use std::bitset to set a bit for equality of each member
std::bitset<4> Short_Vector::operator==(const Short_Vector& obj){
std::bitset<4> r;
r[0] = (a == obj.a);
r[1] = (b == obj.b);
r[2] = (c == obj.c);
r[3] = (d == obj.d);
return r;
}
And you can use it like
Short_Vector a(1,2,3,4);
Short_Vector b(1,0,3,4);
std::bitset<4> res = (a==b);
std::cout << res;
Should give you
1011
std::bitset is good because it provides convenient methods like all any and none (and many more). So that you can check aggregate values with ease.

If you want to have the result as a Short_Vector, try this:
Short_Vector Short_Vector::operator==(const Short_Vector& obj) {
return Short_Vector(
a == obj.a,
b == obj.b,
c == obj.c,
d == obj.d
);
}

The comma operator won't work the way you presumed. It will actually evaluate each of its operands and return the last. The compiler gave you a warning about this little misconception.
One alternative is to set each bit containing the numeric true/false equivalent of your boolean expressions:
unsigned int n = 0;
n |= (a == obj.a) << 0;
n |= (b == obj.b) << 1;
n |= (c == obj.c) << 2;
n |= (d == obj.d) << 3;
return n;
You can use a smaller datatype like char or you can use std::bitset.

If you must use an int as a return type, you could use the left shift operator and do something like:
int result = 0;
result += a_tf << 3; //Shifts the bit 3 places to the left.
result += b_tf << 2; //Shifts the bit 2 places to the left.
result += c_tf << 1; //Shifts the bit 1 place to the left.
result += d_tf; //Puts d_tf as bit 0
return result;
And to get each one back out use the bit-wise and:
result = obj1 == obj2; //Where obj1 and 2 are your compared objects
int a_tf = (result >> 3) & 1;
int b_tf = (result >> 2) & 1;
int c_tf = (result >> 1) & 1;
int d_tf = result & 1;
Though I have to say Named's solution using a bitset is more easily understood, and inserting/retrieving a single value is much easier that way.

Related

What does this arithmetic expression mean: A += B++ == 0 in C++;

I came accross this expression, and can't understand the meaning of line 3 in the following snippet:
int A=0, B=0;
std::cout << A << B << "\n"; // Prints 0, 0
A += B++ == 0; // how does this exp work exactly?
std::cout << A << B << "\n"; // Prints 1, 1
A adds B to it, and B is Post incremented by 1, what does the "==0" mean?
Edit:
Here's the actual code:
int lengthOfLongestSubstringKDistinct(string s, int k) {
int ctr[256] = {}, j = -1, distinct = 0, maxlen = 0;
for (int i=0; i<s.size(); ++i) {
distinct += ctr[s[i]]++ == 0; //
while (distinct > k)
distinct -= --ctr[s[++j]] == 0;
maxlen = max(maxlen, i - j);
}
return maxlen;
}
B++ == 0
This is a boolean expression resulting in true or false. In this case the result is true, true is then added to A. The value of true is 1 so the (rough) equivalent would be:
if(B == 0)
A += 1;
++B;
Note that this isn't particulary good or clear to read code and the person who wrote this should be thrown into the Gulags.
Lets break this expression into pieces: A += value, whereas value = B++ == 0. As later cout suggests, value == 1. Why is that? Here is why: value is result of comparison of B++ and 0, but ++ (increment) operation, when written after operand, is being processed after the comparison, i.e. if you write A += ++B == 0 the later cout should (and does) print 0, 1.

How to write a recursive function that jumbles up numbers from 0 to 6 in a random manner?

Basically i want to write a function that takes values from 0 to 6 and gives back a random assortment such as 2,3,4,5,0,1,6. Here is the code that i came up with. However the problem is that the integer prev (meaning previous) does not store all the old values of r (random number) and thus some values end up being repeated. How might i fix this?
int s(int b)
{
// b is 7
int h = b-1;
int prev = -1;// to store the previous r value
srand(time(0));
for (int i = 0; i < b; i++)
{
int r = rand()%(h - 0 + 1) + 0;
if (r != prev)
{
cout << r << endl;
prev = r;
}
else if (r == prev)
{
s(b);
}
}
return 0;
}
From the comments, this sounds more like a homework problem than a practical problem because you said "No arrays allowed". But I suppose it is an interesting problem.
Here's some code, in Java with only loops, if statements, and with no arrays, as required.
It outputs a random permutation of the set 0, 1, ..., N, shuffled with the Fisher-Yates algorithm.
void printRandom(int N) {
long used = 0;
for (int i = 0; i < N; i++) {
int randomIndex = ThreadLocalRandom.current().nextInt(N - Long.bitCount(used));
for (int j = 0; j < N; j++) {
if ((used & (1L << j)) == 0) {
if (randomIndex-- == 0) {
System.out.print(j + " ");
used = used | (1L << j);
break;
}
}
}
}
}
It is unfortunately limited to the size of a long on your system :)
I think the best way to solve this problem is by using an aux funtion that stores in a variable all the numbers printed until the moment, check if the new number is in the used numbers variable, if not add it to the variable (you can use strings? I know that they are arrays of char's but maybe you can)
Something like this:
function aux(int b, char *variables_printed, int iterations_left)
if (b = 0) then print variables_printed
else
int n = generate_random_number() %b
while (n in variables_printed)
n= (n+random_number) % b
variables_printed += n
aux(b, variables_printed, iterations_left-1)
And your other function:
function s(b)
if b < 0 return 0
else
char *variables_to_print
aux(b, variables_to_print, b)
If you can not use strings, you can do it with long as konsolas said.

Is there a more elegant syntax for these boolean expressions?

I was just writing an improved linear version of a recursive Fibonacci algorithm, and realized that my boolean expressions look really bad and unreadable. Is there a cleaner way to do what I'm trying to do?
int fibonacci(int num) {
if (num <= 1)
return num;
// starts looking ugly here
int a = intExists(num-1);
int b = intExists(num-2);
bool aAndB = (a != -1 && b != -1);
bool justA = (a != -1 && b == -1);
bool justB = (a == -1 && b != -1);
int number = 0;
if (aAndB)
number = (a + b);
else if (justA)
number = (a + fibonacci(num - 2));
else if (justB)
number = (fibonacci(num-1) + b);
else
number = (fibonacci(num - 1) + fibonacci(num - 2));
map.push_back(Pair(num, number));
return number;
}
Thanks
If you're talking about:
bool aAndB = (a != -1 && b != -1);
then I would say, "no."
This code looks perfectly expressive to me. aAndB is initialized at the moment it comes in to being, and the conditions are very clear. This might look a bit odd when you're first starting out in C++, but before you know it it will be second nature and other constructs will seem silly.
One thing I would suggest is to make aAndB const if you don't intend to change it:
const bool aAndB = (a != -1 && b != -1);
This is even more expressive.
It also might give the compiler an additional opportunity to optimize your code.
Remember -- write code for humans to understand. Not for computers to understand.
Why don't you make a and b as bools and assign those as true if a == -1 and false otherwise. Then, the expressions will become easier to handle.
Could do a switch statement to clean up the if else statements a little. Other than that just add comments
You could rewrite it to use conditional branching, like this:
int fibonacci(int num) {
if (num <= 1)
return num;
int a = intExists(num-1);
int b = intExists(num-2);
const bool isA = (a != -1); // change in the definition
const bool isB = (b != -1); // change in the definition
int number = 0;
if (isA && isB)
number = (a + b);
else if (isA) // conditionnal branching
number = (a + fibonacci(num - 2));
else if (isB) // conditionnal branching
number = (fibonacci(num-1) + b);
else
number = (fibonacci(num - 1) + fibonacci(num - 2));
map.push_back(Pair(num, number));
return number;
}
I'm assuming that intExists(n) looks up map and if finds n in there, returns fibonacci(n) else it returns -1. Then you could do this:
int fibonacci(int num) {
if (num <= 1)
return num;
int a = intExists(num-1);
int b = intExists(num-2);
if (a == -1) // if a wasn't found, then compute it
a = fibonacci(num-1);
if (b == -1) // if b wasn't found, then compute it
b = fibonacci(num-2);
int number = a + b;
map.push_back(std::make_pair(num, number));
return number;
}
Bonus:
Here is another completely different implementation of fibonnacci() based on Binet's formula:
#include <cmath>
int fibonacci(int n) {
static const double e1 = 1.6180339887498948482045868343656; // = (1 + sqrt(5)) / 2
static const double e2 = -0.61803398874989484820458683436564; // = (1 - sqrt(5)) / 2
static const double c = 0.44721359549995793928183473374626; // = 1 / sqrt(5);
double f = c * (std::pow(e1, n) - std::pow(e2, n));
return static_cast<int>(f + 0.5);
}
int main() {
for (int n = 1; n < 15; ++n)
std::cout << fibonacci(n) << ' ';
}
It outputs:
1 1 2 3 5 8 13 21 34 55 89 144 233 377
Plain C++ code is clean enough:
bool a = intExists(num-1);
bool b = intExists(num-2);
if (a && b) {
//
} else if (a) {
//
} else if (b) {
//
} else {
//
}
int a = intExists(num-1);
int b = intExists(num-2);
bool aAndB = (a != -1 && b != -1);
bool justA = (a != -1 && b == -1);
bool justB = (a == -1 && b != -1);
Quick look into the approach you took. Under what circumstances can justB be true? (Hint: never)
That should help you simplify your approach, although there are better approaches than memoization.
Changing intExists to return boolean values, you can do a switch-case statements like that:
bool a = intExists(num-1);
bool b = intExists(num-2);
switch ((a << 1) + b) {
default: // none exists
case 1: // only b exist
case 2: // only a exist
case 3: // both exists
}
The rationale is to transform those booleans in a binary number
A slightly drastic rewrite is to let an external function handle the lookup table.
That way you don't need to care about more than one value at a time.
This one uses map so I didn't have to write so much in order to test it, but it should be easy enough to adapt:
std::map<int, int> table;
int fibonacci(int num);
int value(int num)
{
int result = table[num];
if (!result)
{
result = fibonacci(num);
table[num] = result;
}
return result;
}
int fibonacci(int num)
{
if (num <= 2)
return 1;
return value(num - 1) + value(num - 2);
}

c++ string (int) + string (int) [duplicate]

This question already has answers here:
How to implement big int in C++
(14 answers)
Closed 9 years ago.
I have 2 strings, both contain only numbers. Those numbers are bigger than max of uint64_t.
How can I still add these 2 numbers and then convert the result to string?
Well, you can either use a bigger datatype (for example a library that deals with large integers), or you can quickly knock up your own.
I would suggest that if this is a one off, you do long addition exactly like you would have learned to do in your first few years of school. You can operate directly on the two strings, add the columns, do the 'carry', and build another string containing the result. You can do all this without any conversion to or from binary.
Here. Just for fun, I knocked up a solution for you:
string Add( const string& a, const string& b )
{
// Reserve storage for the result.
string result;
result.reserve( 1 + std::max(a.size(), b.size()) );
// Column positions and carry flag.
int apos = a.size();
int bpos = b.size();
int carry = 0;
// Add columns
while( carry > 0 || apos > 0 || bpos > 0 )
{
if( apos > 0 ) carry += a[--apos] - '0';
if( bpos > 0 ) carry += b[--bpos] - '0';
result.push_back('0' + (carry%10));
carry /= 10;
}
// The result string is backwards. Reverse and return it.
reverse( result.begin(), result.end() );
return result;
}
Note that, for clarity, this code doesn't even attempt to handle errors. It also doesn't do negatives, but it's not hard to fix that.
You need a a BigInt implementation. You can find several different ones here.
Whatever BigInt implementation you choose, needs to have conversion to and from string (they usually do).
Here is the code for your question:
#include <iostream>
#include <string>
using namespace std;
string StrAdd(string a, string b) {
string::reverse_iterator rit_a = a.rbegin();
string::reverse_iterator rit_b = b.rbegin();
string c;
int val_c_adv = 0;
while(rit_a != a.rend() && rit_b != b.rend() ) {
int val_a_i = *rit_a - '0';
int val_b_i = *rit_b - '0';
int val_c_i = val_a_i + val_b_i + val_c_adv;
if(val_c_i >= 10 ) {
val_c_adv = 1;
val_c_i -= 10;
} else {
val_c_adv = 0;
}
c.insert(0,1, (char)(val_c_i+'0'));
++rit_a;
++rit_b;
}
if(rit_a == a.rend() ) {
while( rit_b != b.rend() ) {
int val_b_i = *rit_b - '0';
int val_c_i = val_b_i + val_c_adv;
if(val_c_i >= 10 ) {
val_c_adv = 1;
val_c_i -= 10;
} else {
val_c_adv = 0;
}
c.insert(0, 1, (char)(val_c_i+'0'));
++rit_b;
}
} else if( rit_b == b.rend() ) {
while( rit_a != a.rend() ) {
int val_a_i = *rit_a - '0';
int val_c_i = val_a_i + val_c_adv;
if(val_c_i >= 10 ) {
val_c_adv = 1;
val_c_i -= 10;
} else {
val_c_adv = 0;
}
c.insert(0, 1, (char)(val_c_i+'0'));
++rit_a;
}
}
return c;
}
int main() {
string res, a, b;
cout << "a=" << endl;
cin >> a;
cout << "b=" << endl;
cin >> b;
res = StrAdd(a, b);
cout << "Result=" << res << endl;
}
If you just want to handle positive numbers without having to worry about bringing in an entire bignum library like GMP (along with its tendency to just abort on out-of-memory errors, something I find unforgivable in a general purpose library), you can roll your own, something like:
static std::string add (const std::string& num1, const std::string& num2) {
// Make num1 the wider number to simplify further code.
int digit, idx1 = num1.length() - 1, idx2 = num2.length() - 1;
if (idx1 < idx2) return add (num2, num1);
// Initialise loop variables.
int carry = 0;
std::string res; // reserve idx1+2 chars if you want.
// Add digits from right until thinner number finished.
while (idx2 >= 0) {
digit = num1[idx1--] - '0' + num2[idx2--] - '0' + carry;
carry = (digit > 9);
res.insert (0, 1, (digit % 10) + '0');
}
// Then just process rest of wider number and any leftover carry.
while (idx1 >= 0) {
digit = num1[idx1--] - '0' + carry;
carry = (digit > 9);
res.insert (0, 1, (digit % 10) + '0');
}
if (carry) res.insert (0, 1, '1');
return res;
}
You can add efficiencies like reserving space in the target string in advance, and setting specific indexes of it rather than inserting but, unless you're handling truly massive strings or doing it many time per second, I usually prefer code that is simpler to understand and maintain .

Test if multiple variable values are either all positive or negative

Is there a good and fast way in C/C++ to test if multiple variables contains either all positive or all negative values?
Say there a 5 variables to test:
Variant 1
int test(int a[5]) {
if (a[0] < 0 && a[1] < 0 && a[2] < 0 && a[3] < 0 && a[4] < 0) {
return -1;
} else if (a[0] > 0 && a[1] > 0 && a[2] > 0 && a[3] > 0 && a[4] > 0) {
return 1;
} else {
return 0;
}
}
Variant 2
int test(int a[5]) {
unsigned int mask = 0;
mask |= (a[0] >> numeric_limits<int>::digits) << 1;
mask |= (a[1] >> numeric_limits<int>::digits) << 2;
mask |= (a[2] >> numeric_limits<int>::digits) << 3;
mask |= (a[3] >> numeric_limits<int>::digits) << 4;
mask |= (a[4] >> numeric_limits<int>::digits) << 5;
if (mask == 0) {
return 1;
} else if (mask == (1 << 5) - 1) {
return -1;
} else {
return 0;
}
}
Variant 2a
int test(int a[5]) {
unsigned int mask = 0;
for (int i = 0; i < 5; i++) {
mask <<= 1;
mask |= a[i] >> numeric_limits<int>::digits;
}
if (mask == 0) {
return 1;
} else if (mask == (1 << 5) - 1) {
return -1;
} else {
return 0;
}
}
What Version should I prefer? Is there any adavantage using variant 2/2a over 1? Or is there a better/faster/cleaner way?
I think your question and what you're looking for don't agree. You asked how to detect if they're signed or unsigned, but it looks like you mean how to test if they're positive or negative.
A quick test for all negative:
if ((a[0]&a[1]&a[2]&a[3]&a[4])<0)
and all non-negative (>=0):
if ((a[0]|a[1]|a[2]|a[3]|a[4])>=0)
I can't think of a good way to test that they're all strictly positive (not zero) right off, but there should be one.
Note that these tests are correct and portable for twos complement systems (anything in the real world you would care about), but they're slightly wrong for ones complement or sign-magnitude. They might can be fixed if you really care.
I guess you mean negative/positive, (un)signed means whether a sign exists at all. This one works for any iterable (this assumes you count 0 as positive):
template <class T>
bool allpos(const T start, const T end) {
T it;
for (it = start; it != end; it++) {
if (*it < 0) return false;
}
return true;
}
// usage
int a[5] = {-5, 3, 1, 0, 4};
bool ispos = allpos(a, a + 5);
Note: This is a good and fast way
This may not be the absolutely extremely superduperfastest way to do it, but it certainly is readable and really fast. Optimizing this is just not worth it.
Variant 1 is the only readable one.
However, you could make it nicer using a loop:
int test(int *a, int n) {
int neg = 0;
for(int i = 0; i < n; i++) {
if(a[i] < 0) neg++;
}
if(neg == 0) return 1;
else if(neg == n) return -1;
else return 0;
}
I agree with previous posters that loops are simpler. The following solution combines Nightcracker's template and ThiefMaster's full solution, with early-outing if a sign-change is detected while looping over the variables (early-outing). And it works for floating point values.
template<typename T>
int testConsistentSigns(const T* i_begin, const T* i_end)
{
bool is_positive = !(*i_begin < 0);
for(const T* it = i_begin + 1; it < i_end; ++it)
{
if((*it < 0) && is_positive)
return 0;
}
if(is_positive)
return 1;
return -1;
}
In terms of speed, I suggest you profile each of your example in turn to discover which is the fastest on your particular platform.
In terms of ease of understanding, I'd say that the first example is the most obvious, though that's just my opinion.
Of course, the first version is a maintenance nightmare if you have more than 5 variables. The second and third variants are better for this, but obviously have a limit of 32 variables. To make them fully flexible, I would suggest keeping counters of the number of positive and negative variables, in a loop. After the end of the loop, just check that one or other counter is zero.
First off, create a method\procedure. That'll boost readability by a whole lot (no matter how you implement it, it'll be cleaner then all the options above).
Second, I think that the function:
bool isNeg(int x) { return x < 0;}
s cleaner then using bit masks, so I'll go with option 1, and when it comes to speed, let the compiler work that out for you in such low-level cases.
The final code should look something like:
int test(int a[5]) {
bool allNeg = true;
bool allPos = true;
for (i = 0; i < 5; i++){
if (isNeg(a[i]) allPos = false;
if (isPos(a[i]) allNeg = false;
}
if (allNeg) return -1;
if (allPos) return 1;
return 0;
}
You could find maximum element, if it is negative then all elements are negative:
template<typename T>
bool all_negative( const T* first, const T* last )
{
const T* max_el = std::max_element( first, last );
if ( *max_el < T(0) ) return true;
else return false;
}
You could use boost::minmax_element to find if all elements are negative/positive in one loop:
template<typename T>
int positive_negative( const T* first, const T* last )
{
std::pair<const T*,const T*> min_max_el = boost::minmax_element( first, last );
if ( *min_max_el.second < T(0) ) return -1;
else if ( *min_max_el.first > T(0) ) return 1;
else return 0;
}
If the sequence is non-empty, the function minmax_element performs at most 3 * (last - first - 1) / 2 comparisons.
If you only need to know less/greater than zero one at a time, or can be content with < and >= you can do it easily with find_if like this:
#include <iostream>
template <class Iter>
int all_neg(Iter begin, Iter end)
{
return std::find_if(begin, end, std::bind2nd(std::greater_equal<int>(), 0)) == end;
}
int main()
{
int a1[5] = { 1, 2, 3, 4, 5 };
int a2[5] = { -1, 2, 3, 4, 5 };
int a3[5] = { -1, -2, -3, -4, -5 };
int a4[5] = { 0 };
std::cout << all_neg(a1, a1 + 5) << ":"
<< all_neg(a2, a2 + 5) << ":"
<< all_neg(a3, a3 + 5) << ":"
<< all_neg(a4, a4 + 5) << std::endl;
}
You can also use a more complicated predicate that keeps track of any pos/neg to answer your original question if you really need that level of detail.