This question already has answers here:
Ternary operator ?: vs if...else
(14 answers)
Closed 3 years ago.
In my C++ code, I have to select between two functions that take the same arguments based on a given condition. I could write:
if (condition)
return foo(a, b, c);
else
return bar(a, b, c);
Or:
return (condition? foo : bar)(a, b, c);
But which of these two ways is faster?
EDIT:
I tried to test using this code:
#include <cmath>
#include <chrono>
#include <iostream>
using namespace std;
void foo(float x, float y, int param)
{
pow(x+y, param);
}
void bar(float x, float y, int param)
{
pow(x+y, param);
}
int main() {
const int loops = 1000;
auto t1 = chrono::high_resolution_clock::now();
for(int i = 0; i < loops; i++)
for(int j = 0; j < loops; j++)
(i==j? foo : bar)(i, j, 2);
auto t2 = chrono::high_resolution_clock::now();
for(int i = 0; i < loops; i++)
for(int j = 0; j < loops; j++)
if(i==j)
foo(i, j, 2);
else
bar(i, j, 2);
auto t3 = chrono::high_resolution_clock::now();
cout << "ternary: " << (chrono::duration_cast<chrono::microseconds>(t2-t1).count()) << "us" << endl;
cout << "if-else: " << (chrono::duration_cast<chrono::microseconds>(t3-t2).count()) << "us" << endl;
return 0;
}
With the updated test code I got:
ternary: 70951us
if-else: 67962us
Migrated from comments:
Any decent compiler will output the same assembly for both. This is next-level premature optimization and something you shouldn't care about. Pick the one that is most readable and fits into your project style. —Sombrero Chicken
There is no problem with the performance. The compiler can generate the same object code for the both cases.
However there is a difference in applying these constructions.
For the conditional operator there must be deduced the common type of its second and third operands.
For example if you have the following functions
void foo( int, int, int ) {}
int bar( int, int, int ) { return 10; }
then you can use the if-statement as it is shown in the demonstrative program
#include <iostream>
void foo( int, int, int ) {}
int bar( int, int, int ) { return 10; }
int main()
{
int x;
std::cin >> x;
if ( x < 10 )
{
foo( x, x, x );
}
else
{
bar( x, x, x );
}
}
However you may not write as it seems an equivalent code
#include <iostream>
void foo( int, int, int ) {}
int bar( int, int, int ) { return 10; }
int main()
{
int x;
std::cin >> x;
x < 10 ? foo( x, x, x ) : bar( x, x, x );
}
because the compiler is unable to deduce the common type of the calls foo( x, x, x ) and bar( x, x, x ). The first one has the type void and the second one has the type int.
Of course you could write instead
x < 10 ? foo( x, x, x ) : ( void )bar( x, x, x );
but sometimes this makes code less readable when compound expressions are used. And moreover sometimes it is even impossible to deduce the common type because there is no explicit or implicit conversion between expressions especially for user-defined types.
Another example. You can write a function to allow the compiler to deduce its return type.
#include <iostream>
constexpr auto factorial( unsigned long long int n )
{
if ( n < 2 )
{
return n;
}
else
{
return n * factorial( n - 1 );
}
}
int main()
{
int a[factorial( 5 )];
std::cout << "The array has " << sizeof( a ) / sizeof( *a ) << " elements\n";
}
The program output is
The array has 120 elements
On the other hand, you may not write
#include <iostream>
constexpr auto factorial( unsigned long long int n )
{
return n < 2 ? n : n * factorial( n - 1 );
}
int main()
{
int a[factorial( 5 )];
std::cout << "The array has " << sizeof( a ) / sizeof( *a ) << " elements\n";
}
The compiler is unable to deduce the return type of the function.
So sometimes there is even no choice between whether to use the if-statement or the conditional expression:)
Related
I want to make a program that takes 4 numbers eg.(a, b, c and d) and checks if using arithmetic operators i can make the first 3 numbers result to the fourth number, like if the input is (3, 4, 5, 23) this will check out true because
3 + 4 * 5 = 23,So i want to make an array that has the operators and use a loop to check every possible combination, Hope i made it clear.
Edit:
Its actually codeforces problem, given 4 numbers. Check whether he could get the fourth number by using the arithmetic operators (+,−,×) between the other three numbers. Knowing that an operator can be used only once. in this format ->(a□b□c=d).My question was if there is a way to make it automatic or do i have to code every possibility manually So sorry for any confusion i may have caused.
You can't store the operators in an array, but you could make wrapper functions for them and store those in an array.
int add(int a, int b) {
return a + b;
}
int sub(int a, int b) {
return a - b;
}
int mul(int a, int b) {
return a * b;
}
int div(int a, int b) {
return a / b;
}
typedef int (*funptr)(int, int);
funptr arr[] = { add, sub, mul, div };
You can then call them like:
(arr[1])(2, 1) // call sub(2, 1)
The parentheses around arr[1] aren't needed in this case, but I like to put them for clarity.
No. You'd have to write a program to work this out. You could store something like function pointers to the arithmetic operators in an array, but I don't think that would help solve your problem. You'd still have to write the code to solve your problem.
Adding onto #CoffeeTableEspresso's answer, you can also put those function pointers into a map.
int add(int a, int b) {
return a + b;
}
int sub(int a, int b) {
return a - b;
}
int mul(int a, int b) {
return a * b;
}
int div(int a, int b) {
return a / b;
}
typedef int (*funptr)(int, int);
std::map<char,funptr> operators = {
{'+', add},
{'-', sub},
{'*', mul},
{'/', div}};
Then you can do
operators['+'](4,7);
Which might be a bit more readable, and you can iterate through these more easily.
I thought I would submit a compete answer. This works for positive numbers. It may take a bit more work to cover all the possibilities. And it does not answer to CoffeeTableEspresso's question about precedence. But it may help with your last question about if statements.
#include <iostream>
namespace {
auto add = [](int a, int b) {return a + b; };
auto sub = [](int a, int b) {return a - b; };
auto mult = [](int a, int b) {return a * b; };
auto divd = [](int a, int b) {return b ? a / b : -1; };
std::vector<int(*)(int, int)> ops = { add,sub,mult,divd };
}
int check(int* params)
{
for (size_t i = 0; i < 4; ++i)
for (size_t j = 0; j < 4; ++j)
{
auto result = ops[i](params[0], ops[j](params[1], params[2]));
if (params[3] == result)
return result;
else
std::cout << result << std::endl;
}
return -1;
}
int main()
{
int params[] = { 3, 4, 5, 23 };
std::cout << check(params);
}
Operators * / have a higher precedence than + -, so operator[i](A, operator[j](B, C)) solution doesn't really work.
You can write a little string calculator, and cycle through char-operators:
#include <iostream>
#include <sstream>
#include <vector>
#include <cmath>
double calculate(std::string str)
{
// calculator there
return -1;
};
int main()
{
std::vector<char> op = {'+', '-', '*', '/'};
std::vector<int> a = { 96, 3, 10, 42 };
for (auto op1: op)
for (auto op2: op)
{
std::stringstream ss;
ss << a[0] << op1 << a[1] << op2 << a[2];
double result = calculate( ss.str());
if (std::abs(a[3] - result) < 1E-6)
std::cout << ss.str() << " = " << a[3];
else
std::cout << ss.str() << " = " << result << " != " << a[3];
}
}
can anybody tell me why my Combination function is always resulting 0 ?
I also tried to make it calculate the combination without the use of the permutation function but the factorial and still the result is 0;
#include <iostream>
#include <cmath>
using namespace std;
int factorial(int& n)
{
if (n <= 1)
{
return 1;
}
else
{
n = n-1;
return (n+1) * factorial(n);
}
}
int permutation(int& a, int& b)
{
int x = a-b;
return factorial(a) / factorial(x);
}
int Combination(int& a, int& b)
{
return permutation(a,b) / factorial(b);
}
int main()
{
int f, s;
cin >> f >> s;
cout << permutation(f,s) << endl;
cout << Combination(f,s);
return 0;
}
Your immediate problem is that that you pass a modifiable reference to your function. This means that you have Undefined Behaviour here:
return (n+1) * factorial(n);
// ^^^ ^^^
because factorial(n) modifies n, and is indeterminately sequenced with (n+1). A similar problem exists in Combination(), where b is modified twice in the same expression:
return permutation(a,b) / factorial(b);
// ^^^ ^^^
You will get correct results if you pass n, a and b by value, like this:
int factorial(int n)
Now, factorial() gets its own copy of n, and doesn't affect the n+1 you're multiplying it with.
While we're here, I should point out some other flaws in the code.
Avoid using namespace std; - it has traps for the unwary (and even for the wary!).
You can write factorial() without modifying n once you pass by value (rather than by reference):
int factorial(const int n)
{
if (n <= 1) {
return 1;
} else {
return n * factorial(n-1);
}
}
Consider using iterative code to compute factorial.
We should probably be using unsigned int, since the operations are meaningless for negative numbers. You might consider unsigned long or unsigned long long for greater range.
Computing one factorial and dividing by another is not only inefficient, it also risks unnecessary overflow (when a is as low as 13, with 32-bit int). Instead, we can multiply just down to the other number:
unsigned int permutation(const unsigned int a, const unsigned int b)
{
if (a < b) return 0;
unsigned int permutations = 1;
for (unsigned int i = a; i > a-b; --i) {
permutations *= i;
}
return permutations;
}
This works with much higher a, when b is small.
We didn't need the <cmath> header for anything.
Suggested fixed code:
unsigned int factorial(const unsigned int n)
{
unsigned int result = 1;
for (unsigned int i = 2; i <= n; ++i) {
result *= i;
}
return result;
}
unsigned int permutation(const unsigned int a, const unsigned int b)
{
if (a < b) return 0;
unsigned int result = 1;
for (unsigned int i = a; i > a-b; --i) {
result *= i;
}
return result;
}
unsigned int combination(const unsigned int a, const unsigned int b)
{
// C(a, b) == C(a, a - b), but it's faster to compute with small b
if (b > a - b) {
return combination(a, a - b);
}
return permutation(a,b) / factorial(b);
}
You dont calculate with the pointer value you calculate withe the pointer address.
I know this has been asked before but I still don't know how to do it. I Have to write a function which returns the number of times 2, 5 and 9 appear in an array.
include <iostream>
int twofivenine(int array[], int n)
{
int i = 0;
int num_2 = 0;
int num_5 = 0;
int num_9 = 0;
for ( i = 0; i < n; i++ ){
switch(){
case (array[i] == 2):
num_2++;
case (array[i] == 5):
num_5++;
case (array[i] == 9):
num_9++;
}
}
return ;
}
int main()
{
int array[6] = {2,2,3,5,9,9};
std::cout << "2: 5: 9:" << twofivenine(array, 6) << std::endl;
}
I'm just not sure how to return (num_2, num_5, and num_9)
Can use std::tuple
std::tuple<int, int, int > twofivenine( int array[], int n)
{
//
return make_tuple( num_2, num_5, num_9 );
}
auto x = twofivenine( array, 6 );
std::cout << std::get<0>( x ) << '\n'
<< std::get<1>( x ) << '\n'
<< std::get<2>( x ) << '\n' ;
There are a number of ways to approach this problem.
Pass the values by reference. You can call a function such as the following:
Example:
void foo(int &a, int &b, int &c)
{
// modify a, b, and c here
a = 3
b = 38
c = 18
}
int first = 12;
int second = 3;
int third = 27;
foo(first, second, third);
// after calling the function above, first = 3, second = 38, third = 18
Store the values to return in a data type. Use a data type from the standard library such as std::vector, std::set, std::tuple, etc. to hold your values then return that entire data member.
Example:
std::vector<int> foo()
{
std::vector<int> myData;
myData.pushBack(3);
myData.pushBack(14);
myData.pushBack(6);
return myData;
}
// this function returns a vector that contains 3, 14, and 6
Create an object to hold your values. Create an object such as a struct or a class to hold your values and return the object in your function.
Example:
struct myStruct
{
int a;
int b;
int c;
};
myStruct foo()
{
// code here that modifies elements of myStruct
myStruct.a = 13;
myStruct.b = 2;
myStruct.c = 29;
return myStruct;
}
// this function returns a struct with data members a = 13, b = 2, and c = 29
The method you choose will ultimately depend on the situation.
Pass objects in by reference, ie
void twofivenine(int array[], int n, int &num_2, int &num_5, int &num_9)
{
//Don't redeclare num_2...
}
Call like so:
int num_2, num_5, num_9;
twofivenine(array, 6, num_2, num_5, num_9);
Return a struct by value which has the counts as the data members:
struct Result {
int num_3;
int num_5;
int num_9;
};
Result twofivenine(int array[], int n)
{
.
.
.
return Result{num_2, num_5, num_9};
}
and in main:
Result result(twofivenine(array, 6));
std::cout << "2: " << result.num_2 << "5: " << result.num_5 << "9: " << result.num_9 << std::endl;
Most compilers will do RVO (return-value-optimization) where the twofivenine function will directly write to the result struct avoiding a struct copy.
i have to write a code that has a function that takes two integers and returns x as (a + b) and y as (a * b) and when i run it, it only outputs y. Why doesnt it output (or return) x?
#include <iostream>
using namespace std;
int math (int a, int b) {
int x, y;
x = a + b;
y = a * b;
return x, y;
}
int main() {
cout << math (5,3);
getchar();
getchar();
return 0;
}
The return type of math is int, so this is what it returns (a single integer).
The expression x, y uses the comma operator. The comma operator evaluates x, discards its value, and then evaluates and returns y. In other words, return x, y is equivalent to return y.
You could use std::pair<int,int> to return a pair of integers.
The line
return x, y;
does not do what you expect. The comma operator returns only the value after the last comma - in this case, y. To return multiple values, you should use a struct or class containing both.
You can only return one thing. You can put those in a struct, and return it. Simpler example.
struct xy {
int x;
int y;
};
xy math(int a, int b) {
xy pair;
int x, y;
pair.x = a + b;
pair.y = a * b;
return pair;
}
There are two ways to make a function return more than one value. The
first is to use out parameters, either references or pointers:
void
math( int a, int b, int& sum, int& product )
{
sum = a + b;
product = a * b;
}
int
main()
{
int s;
int p;
math(5, 3, s, p);
std::cout << s << ' ' << p << std::endl;
return 0;
}
The other is to define a class to contain the two values:
struct MathResults
{
int sum;
int product;
};
MathResults
math( int a, int b )
{
return MathResults{ a + b, a * b };
}
std::ostream&
operator<<( std::ostream& dest, MathResults const& value )
{
dest << value.sum << ' ' << value.product;
}
int
main()
{
std::cout << math( 5, 3 ) << std::endl;
return 0;
}
In most cases, the second solution is to be preferred.
I've having trouble understanding the wording of this question and what it means by returning the second value through a pointer parameter?
The problem is:
Write a function that takes input arguments and provides two seperate results to the caller, one that is the result of multiplying the two argumentsm the other the result of adding them. Since you can directly return only one value from a funciton you'll need the seecond value to be returned through a pointer or references paramter.
This is what I've done so far.
int do_math(int *x, int *y)
{
int i =*x + *y;
int u = *x * *y;
int *p_u = &u;
return i;
}
void caller()
{
int x = 10;
int y = 5;
std::cout << do_math(&x, &y);
//std::cout << *u;
}
I think all they're wanting you to do is to demonstrate your understanding of the difference between passing arguments by value and passing them by reference.
Here is a sample code that shows that although my function is only returning one value "i = X+Y", It is also changing the value of Y to (Y * X).
Of course if you do need Y's value to stay unchanged, you could use a third variable that is equal to Y's value and pass its reference as an extra argument to your function.
You could run the code bellow to see what's happening to X and Y before and after calling the function.
Hope this helps.
#include <iostream>
using namespace std;
int do_math(int value1, int *pointer_to_value2)
{
int i = value1 * *pointer_to_value2;
*pointer_to_value2 = *pointer_to_value2 + value1; // y changes here
return i;
}
int main( int argc, char ** argv ) {
int x = 10;
int y = 5;
cout << "X before function call " << x << endl;
cout << "Y before function call " << y << endl;
int product = do_math(x, &y);
cout << "X after function call " << x << endl;
cout << "Y after function call " << y << endl;
cout << "What the function returns " << product << endl;
return 0;
}
In the assignment there is written
Write a function that takes input arguments ...
So there is no any need to declare these input parameters as pointers.
The function could look like
int do_math( int x, int y, int &sum )
{
sum = x + y;
return x * y;
}
or
int do_math( int x, int y, int *sum )
{
*sum = x + y;
return x * y;
}
In these function definitions the sum and the product can be exchanged as the parameter and return value
As for me the I would write the function either as
void do_math( int x, int y, long long &sum, long long &product )
{
sum = x + y;
product = x * y;
}
or
#include <utility>
//...
std::pair<long long, long long> do_math( int x, int y )
{
return std::pair<long long, long long>( x + y, x * y );
}
void caller()
{
int x = 10;
int y = 5;
std::pair<long long, long long> result = do_math( x, y );
std::cout << "Sum is equal to " << result.first
<< " and product is equal to " << result.second
<< std::endl;
}
Edit: I would like to explain why this statement
std::cout << "sum is " << do_math(x, y, result) << " and result is " << result;
is wrong.
The order of evaluation of subexpressions and function argument is unspecified. So in the statement above some compilers can output value of result before evaluation function call do_math(x, y, result)
So the behaviour of the program will be unpredictable because you can get different results depending on using the compiler.
Edit: As for your code from a comment then it should look like
#include <iostream>
int do_math( int x, int y, int *p_u )
{
int i = x + y;
*p_u = x * y;
return i;
}
int main()
{
int x = 10;
int y = 5;
int u;
int i = do_math( x, y, &u );
std::cout << i << std::endl;
std::cout << u << std::endl;
}
Also take into account that in general case it is better to define variables i and u as having type long long because for example the product of two big integers can not fit in an object of type int.
The wording is kind of contrived but I believe the task asks you to
return the multiplication as the return value of the function, and
since you can't return two types at once (except if you wrap them up somehow), you should use a third parameter as a storage area for the sum:
#include <iostream>
/* Multiplication in here */ int do_math(int x, int y, int& result/* Addition in here */)
{
result = x + y;
return x*y;
}
int main() {
int x = 10;
int y = 5;
int addition = 0;
int multiplication = do_math(x, y, addition);
std::cout << "multiplication is " << multiplication << " and sum is " << addition;
}
Example
It's not specifically asking you to use two parameters for the function.
A typical solution to the intent of the exercise text…
” Write a function that takes input arguments and provides two seperate results to the caller, one that is the result of multiplying the two argumentsm the other the result of adding them. Since you can directly return only one value from a funciton you'll need the seecond value to be returned through a pointer or references paramter
… is
auto product_and_sum( double& sum, double const a, double const b )
-> double
{
sum = a + b;
return a*b;
}
#include <iostream>
using namespace std;
auto main() -> int
{
double product;
double sum;
product = product_and_sum( sum, 2, 3 );
cout << product << ", " << sum << endl;
}
This code is unnatural in that one result is returned while the other is an out-argument.
It's done that way because the exercise text indicates that one should do it that way.
A more natural way to do the same is to return both, as e.g. a std::pair:
#include <utility> // std::pair, std::make_pair
using namespace std;
auto product_and_sum( double const a, double const b )
-> pair<double, double>
{
return make_pair( a*b, a+b );
}
#include <iostream>
#include <tuple> // std::tie
auto main() -> int
{
double product;
double sum;
tie( product, sum ) = product_and_sum( 2, 3 );
cout << product << ", " << sum << endl;
}
As the second program illustrates, the last sentence of the exercise text,
” Since you can directly return only one value from a funciton you'll need the seecond value to be returned through a pointer or references paramter
… is just not true. I suspect the author had meant the word “directly” to clarify that this excluded the case of a non-basic type. But even so the conclusion is incorrect.
What you need to do is provide another parameter to the function - the pointer or the reference to the variable where you want to store your other result:
int do_math(int *x, int *y, int &res) //or int *res
{
...
res = *x * *y;
...
}
Then make a result variable in main and pass it to the function