I want to find the minimum number using STL in C++, I know the syntax should be min(x,y). But I want to find the minimum +ve numbers in the list. Not inlcuding the -ves. How do I do that?
P.S My numbers are in an array
For finding the minimum number, it makes sense to use std::min_element. Fortunately, it comes with an optional comparison parameter, which we can make use of: (sample here)
auto pos = std::min_element(std::begin(arr), std::end(arr),
[](const T &t1, const T &t2) {return t1 > 0 && (t2 <= 0 || t1 < t2);}
);
You just have to be careful to take into account that if it's comparing a positive t1 to a negative number, it should always be true. If none of the elements are positive, this will give the location of the first number in the array. If 0 should be treated as part of the positives, change t1 > 0 to t1 >= 0 and t2 <= 0 to t2 < 0.
I'd use std::accumulate with a suitable operation:
auto minpos = std::accumulate(myrange.begin(), myrange.end(), MAX_VALUE,
[](T acc, T x)
{ return (x > 0 && x < acc) ? x : acc; });
Here T is the type of your elements and MAX_VALUE is the maximal value of that type (e.g. defined as std::numeric_limits<T>::max()).
First use the remove_if algorithm to move all the negative numbers to the end of the collection, then call min_element on the positive range. In C++11
auto pos = remove_if(coll.begin(), coll.end(), [](int x){ return x < 0; });
auto min = *min_element(coll.begin(), pos);
If you're not using C++11 just replace the lambda with a pre-canned functor from like less<>
You may use std::min_element with Boost::filter_iterator
Something like:
struct is_positive_number {
bool operator()(int x) const { return 0 < x; }
};
void foo(const std::vector<int>& numbers)
{
typedef boost::filter_iterator<is_positive_number, base_iterator> FilterIter;
is_positive_number predicate;
FilterIter filter_iter_begin(predicate, begin(numbers), end(numbers + N));
FilterIter filter_iter_end(predicate, end(numbers + N), end(numbers + N));
FilterIter it = std::min_element(filter_iter_begin, filter_iter_end);
if (it != filter_iter_end) {
// *it is the min elem
} else {
// no positive numbers.
}
}
Related
I have already computed the truncated mean of a vector via the function truncated_mean(std::vector& v, double trimming fraction). This function takes as inputs the vector v and the fraction that we want to remove to calculate the mean (e.g. 10% so we remove the highest and lowest 10% values and then we compute the mean), I created it using the Standard Library.
For example, v = [0,1,2....,9], then truncated_mean(v, 0.10) = 4.5.
Now, I want to reuse the same function but instead of having v as input, I want to have 2 forward iterators, v.begin() and v.end(). I am provided with the template of typename forward that I should use to check if its value_type (accessed via std::iterator_traits) meets a certain criteria. My understanding of the problem is that first I need to check if the inputs belong to a vector and from there I should access the vector in itself to compute the truncated mean.
How can I adapt my function to take as input the beginning and end of the vector rather than the vector itself?
Assuming sequence passed in is sorted you could simply use std::distance to figure out the length and skip the appropriate number of elements at the start and the end:
Edit: Extended code to use std::accumulate for random access iterators; Use concepts instead of distinguishing iterator types vis additional parameter, if you're allowed to use C++20 features.
template<typename RandomAccessIterator>
double truncated_mean_impl(RandomAccessIterator begin, RandomAccessIterator end, double trimming_fraction, std::random_access_iterator_tag)
{
if (trimming_fraction < 0)
{
throw std::range_error("trimming_fraction must not be negative");
}
if(trimming_fraction >= 0.5)
{
return std::numeric_limits<double>::quiet_NaN(); // no elements left after trimming
}
auto const count = std::distance(begin, end);
auto const skippedElementCountFront = static_cast<decltype(count)>(count * trimming_fraction);
auto const summandCount = count - 2 * skippedElementCountFront;
return std::accumulate<RandomAccessIterator, double>(begin + skippedElementCountFront, end - skippedElementCountFront, 0) / summandCount;
}
template<typename ForwardIterator>
double truncated_mean_impl(ForwardIterator begin, ForwardIterator end, double trimming_fraction, std::forward_iterator_tag)
{
if (trimming_fraction < 0)
{
throw std::range_error("trimming_fraction must not be negative");
}
if(trimming_fraction >= 0.5)
{
return std::numeric_limits<double>::quiet_NaN(); // no elements left after trimming
}
auto const count = std::distance(begin, end);
auto const skippedElementCountFront = static_cast<decltype(count)>(count * trimming_fraction);
// skip elements in the front
for (auto i = skippedElementCountFront; i != 0; --i, ++begin) {}
auto const summandCount = count - 2 * skippedElementCountFront;
double sum = 0;
for (auto i = summandCount; i != 0; --i, ++begin)
{
sum += *begin;
}
return sum / summandCount;
}
template<typename ForwardIterator>
double truncated_mean(ForwardIterator begin, ForwardIterator end, double trimming_fraction)
{
return truncated_mean_impl<ForwardIterator>(begin, end, trimming_fraction, typename std::iterator_traits<ForwardIterator>::iterator_category());
}
int main()
{
std::vector<int> const values { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
std::cout << truncated_mean(values.cbegin(), values.cend(), 0.1) << '\n';
}
If the input sequence is not sorted and you cannot or don't want to sort the input copying the elements to a new vector and applying your original algorithm to this vector would probably be best.
I'd like to store a bunch of range items in std::set container.
This data structure should provide fast decision whether a specific input range contained by one of the ranges that the set currently holds, by overloading the comparison of std::set in order use the set::find method to check one of the items in set contain the input range argument.
It should also support range item that represents a single point (start_range == end_range).
Here's my implementation :
#include <iostream>
#include <map>
#include <set>
using std::set;
using std::map;
class range : public std::pair<int,int>
{
public:
range(int lower, int upper)
{
if (upper < lower)
{
first = upper;
second = lower;
}
else
{
first = lower;
second = upper;
}
}
range(int val)
{
first = second = val;
}
bool operator<(range const & b) const
{
if (second < b.first)
{
return true;
}
return false;
}
};
And here's how I test my data structure:
int main(int argc, const char * argv[])
{
std::map<int, std::set<range>> n;
n[1].insert(range(-50,-40));
n[1].insert(range(40,50));
n[2].insert(range(-30,-20));
n[2].insert(range(20,30));
n[3].insert(range(-20,-10));
n[3].insert(range(10,20));
range v[] = {range(-50,-41), range(30,45), range(-45,-45), range(25,25)};
int j[] = {1,2,3};
for (int l : j)
{
for (range i : v)
{
if (n[l].find(i) != n[l].end())
{
std::cout << l << "," << i.first << "," << i.second << " : "
<< n[l].find(range(i))->first << " "
<< n[l].find(range(i))->second << std::endl;
}
}
}
}
and here are the results I get:
1,-50,-41 : -50 -40 --> good
1,30,45 : 40 50 --> bad
1,-45,-45 : -50 -40 --> good
2,30,45 : 20 30 --> bad
2,25,25 : 20 30 --> good
So as you can see, my code does support perfectly well single point range (-45 is contained by range (-50,-40) and 25 is contained by by range (20,30))
However, as for wider ranges, my current operator < is capable of finding the contained relationship which is equal for the set terminology (meaning that for ranges a and b a<b && a<b.
Is there anyway to change this operator to make it work ?
Sounds like a perfect match for using Boost Interval Container Library. In short, you can
#include <boost/icl/interval_set.hpp>
// Helper function template to reduce explicit typing:
template <class T>
auto closed(T&& lower, T&& upper)
{
return boost::icl::discrete_interval<T>::closed(std::forward<T>(lower),
std::forward<T>(upper));
}
boost::icl::interval_set<int> ranges;
ranges.insert(closed(1, 2));
ranges.insert(closed(42, 50));
std::cout << contains(ranges, closed(43, 46)) << "\n"; // true
std::cout << contains(ranges, closed(42, 54)) << "\n"; // false
This should easily be pluggable into your std::map and be usable without further adjustments.
Your operator < defines partial order:
(30,45) < (40, 50) == false and simultaneously (40, 50) < (30, 45) == false so in terms of std::set and std::map they are equal. That is why you got these results.
There is a paper about partial order: https://en.wikipedia.org/wiki/Partially_ordered_set
You might want use std::unordered_map or define somehow total order for your ranges.
I suggest operator < that compares the arithmetical mean of range bounds, i.e.
(a, b) < (c, d) if and only if (a+b)/2 < (c+d)/2 for total order. Note that you might want use float for arithmetical mean.
For testing I suggest the following code draft (I write here from scratch and didn't tested it). -1 meanst that are no range that contains this
int range::firstContainsMe(const std::vector<range> rangesVec)
{
for (size_t i = 0; i < rangesVec; i++) {
if (lower >= rangesVec[i].lower && upper <= rangesVec[i].upper) {
return i;
}
}
return -1;
}
Your comparison operator is unsuitable.
If you wish to use any container or algorithm based on ordering in C++, the ordering relation needs to be a Strict Weak Ordering Relation. The definition can be found on Wikipedia, in short the following rules must be respected:
Irreflexivity: For all x in S, it is not the case that x < x.
Asymmetry: For all x, y in S, if x < y then it is not the case that y < x.
Transitivity: For all x, y, z in S, if x < y and y < z then x < z.
Transitivity of Incomparability: For all x, y, z in S, if x is incomparable with y (neither x < y nor y < x hold), and y is incomparable with z, then x is incomparable with z.
Your comparison operator fails, and therefore is unsuitable. In general, a quick way of obtaining a good comparison operator is to do what tuples do:
bool operator<(range const & b) const
{
return std::tie(first, second) < std::tie(b.first, b.second);
}
You want a map, not a set.
In order to solve your problem, you want a map, not a set.
For disjoint intervals, a map from lower-bound to upper-bound is sufficient:
std::map<int, int> intervals;
The .lower_bound and .upper_bound operations allow finding the closest key in O(log N) time, and from there containment is quickly asserted.
For non-disjoint intervals, things get trickier I fear, and you'll want to start looking into specialized data-structures (Interval Trees for example).
Like the title says I am trying to use a binary search method to search a sorted vector for the closest given value and return its index. I have attempted to use lower/upper_bound() but the returned value is either the first or last vector value, or "0". Below is the txt file which i have read the temp and voltage into vectors.
1.4 1.644290 -12.5
1.5 1.642990 -13.6
1.6 1.641570 -14.8
1.7 1.640030 -16.0
1.8 1.638370 -17.1
This is my current linear search that works
double Convert::convertmVtoK(double value) const
{
assert(!mV.empty());
auto it = std::min_element(mV.begin(), mV.end(), [value] (double a, double b) {
return std::abs(value - a) < std::abs(value - b);
});
assert(it != mV.end());
int index = std::distance(mV.begin(), it);
std::cout<<kelvin[index];
return kelvin[index];
}
This is the algorithm I am currently trying to get working to improve performance.
double Convert::convertmVtoK(double value)
{
auto it = lower_bound(mV.begin(), mV.end(), value);
if (it == mV.begin())
{
it = mV.begin();
}
else
{
--it;
}
auto jt = upper_bound(mV.begin(), mV.end(), value), out = it;
if (it == mV.end() || jt != mV.end() && value - *it > *jt - value)
{
out = jt;
}
cout<<"This is conversion mV to K"<<" "<< *out;
Any suggestions would be much appreciated. I believe the issue may lie with the vector being sorted in descending order but i need the order to remain the same in order to compare the values.
SOLVED thanks to #John. For anyone who needs this in the future here is what works.
double Convert::convertmVtoK(double value) const
{
auto it = lower_bound(mV.begin(), mV.end(), value, [](double a, double b){ return a > b; });
int index = std::distance(mV.begin(), it);
std::cout<<kelvin[index];
}
Since you have a non-increasing range (sorted in descending order), you can use std::lower_bound with a greater than operator, as mentioned in comments. However, this only gets you the first result past or equal to your number. It doesn't mean it's the "closest", which is what you asked for.
Instead, I would use std::upper_bound, so you don't have to check for equality (on double just to make it worse) and then drop back one to get the other bounding data point, and compute which one is actually closer. Along with some boundary checks:
#include <vector>
#include <algorithm>
#include <iostream>
#include <functional>
#include <iterator>
// for nonincreasing range of double, find closest to value, return its index
int index_closest(std::vector<double>::iterator begin, std::vector<double>::iterator end, double value) {
if (begin == end){
// we're boned
throw std::exception("index_closest has no valid index to return");
}
auto it = std::upper_bound(begin, end, value, std::greater<double>());
// first member is closest
if (begin == it)
return 0;
// last member is closest. end is one past that.
if (end == it)
return std::distance(begin, end) - 1;
// between two, need to see which is closer
double diff1 = abs(value - *it);
double diff2 = abs(value - *(it-1));
if (diff2 < diff1)
--it;
return std::distance(begin, it);
}
int main()
{
std::vector<double> data{ -12.5, -13.6, -14.8, -16.0, -17.1 };
for (double value = -12.0; value > -18.99; value = value - 1.0) {
int index = index_closest(data.begin(), data.end(), value);
std::cout << value << " is closest to " << data[index] << " at index " << index << std::endl;
}
}
output
-12 is closest to -12.5 at index 0
-13 is closest to -12.5 at index 0
-14 is closest to -13.6 at index 1
-15 is closest to -14.8 at index 2
-16 is closest to -16 at index 3
-17 is closest to -17.1 at index 4
-18 is closest to -17.1 at index 4
Note that, e.g. -14 is closer to -13.6 than -14.8, as a specific counterexample to your current working point. Also note the importance of inputs at both end points.
From there you are welcome to take kelvin[i]. I wasn't happy with using an external data array for the function's return value when you don't need to do that, so I just returned the index.
You might use the following to get the iterator with closest value:
auto FindClosest(const std::vector<double>& v, double value)
{
// assert(std::is_sorted(v.begin(), v.end(), std::greater<>{}));
auto it = std::lower_bound(v.begin(), v.end(), value, std::greater<>{});
if (it == v.begin()) {
return it;
} else if (it == v.end()) {
return it - 1;
} else {
return std::abs(value - *it) < std::abs(value - *(it - 1)) ?
it : it - 1;
}
}
This method works but am not 100% sure it always gives closest value. Incorporated part of #KennyOstrom 's method.
double Convert::convertmVtoK(double value) const
{
auto it = lower_bound(mV.begin(), mV.end(), value, [](double a, double b){ return a > b; });
int index = std::distance(mV.begin(), it);
if(value>mV[0] || value < mV.back())
{
std::cout<<"Warning: Voltage Out of Range"<<"\n";
}
else if(value==mV[0] || value==mV.back()
||fabs(value - mV[index]) <= 0.0001 * fabs(value))
{
std::cout<<kelvin[index];
return kelvin[index];
}
else
{
double diff1 = std::abs(value - mV[index]);
double diff2 = std::abs(value - mV[index-1]);
if (diff2 < diff1)
{
std::cout<<kelvin[index-1];
return kelvin[index-1];
}
else
{
std::cout<<kelvin[index];
return kelvin[index];
}
}
}
I am using a simple function (y(x)), and I want to generate an x value from a certain y value. While typically reverse mapping does not give a single x value, I am using the maximum from my y values. This means that there will be a unique x value for the y value I input(the maximum). I don't understand how to code this in c++
If you don't need interpolation, only exact reverse lookup, then it's relatively straighforward:
std::map<YType, XType> lookup;
// (code to read the file goes here)
// for each x {
YType y = f(x);
if ((lookup.count(y) == 0) || (lookup[y] < x)) {
lookup[y] = x;
}
// }
Then your reverse lookup is just lookup[y], which will return 0 (or a default-constructed value where applicable) if y in fact was missing from the data.
Be aware that my code is a bit inefficient, it looks up y several times in the map, up to 3. You can optimize using iterators, but I'm concerned that obscures what's going on if you're not already familiar with them:
typedef std::map<YType, XType> maptype;
typedef std::pair<maptype::iterator, bool> resulttype;
resulttype result = lookup.insert(std::make_pair(y, x));
if (!result.second) {
// key already existed, so value was not inserted. Check for max.
maptype::iterator pos = result.first;
if ((*pos).second < x) {
(*pos).second = x;
}
}
If I understand correctly, you are given a finite range of values x, say x[0], x[1], ..., x[N], and a function f, and you want to find the index k for which f(x[k]) is the largest possible. In that case, a simple search will do:
size_t k = 0;
T m = f(x[k]);
T tmp;
for (size_t i = 1; i <= N; ++i)
{
if ((tmp = f(x[i])) > m)
{
k = i;
m = tmp;
}
}
// Maximum is (x[k], m)
Here T is the type such that f is T f(T);
Simple question - In c++, what's the neatest way of getting which of two numbers (u0 and u1) is the smallest positive number? (that's still efficient)
Every way I try it involves big if statements or complicated conditional statements.
Thanks,
Dan
Here's a simple example:
bool lowestPositive(int a, int b, int& result)
{
//checking code
result = b;
return true;
}
lowestPositive(5, 6, result);
If the values are represented in twos complement, then
result = ((unsigned )a < (unsigned )b) ? a : b;
will work since negative values in twos complement are larger, when treated as unsigned, than positive values. As with Jeff's answer, this assumes at least one of the values is positive.
return result >= 0;
I prefer clarity over compactness:
bool lowestPositive( int a, int b, int& result )
{
if (a > 0 && a <= b) // a is positive and smaller than or equal to b
result = a;
else if (b > 0) // b is positive and either smaller than a or a is negative
result = b;
else
result = a; // at least b is negative, we might not have an answer
return result > 0; // zero is not positive
}
Might get me modded down, but just for kicks, here is the result without any comparisons, because comparisons are for whimps. :-)
bool lowestPositive(int u, int v, int& result)
{
result = (u + v - abs(u - v))/2;
return (bool) result - (u + v + abs(u - v)) / 2;
}
Note: Fails if (u + v) > max_int. At least one number must be positive for the return code to be correct. Also kudos to polythinker's solution :)
unsigned int mask = 1 << 31;
unsigned int m = mask;
while ((a & m) == (b & m)) {
m >>= 1;
}
result = (a & m) ? b : a;
return ! ((a & mask) && (b & mask));
EDIT: Thought this is not so interesting so I deleted it. But on the second thought, just leave it here for fun :) This can be considered as a dump version of Doug's answer :)
Here's a fast solution in C using bit twiddling to find min(x, y). It is a modified version of #Doug Currie's answer and inspired by the answer to the Find the Minimum Positive Value question:
bool lowestPositive(int a, int b, int* pout)
{
/* exclude zero, make a negative number to be larger any positive number */
unsigned x = (a - 1), y = (b - 1);
/* min(x, y) + 1 */
*pout = y + ((x - y) & -(x < y)) + 1;
return *pout > 0;
}
Example:
/** gcc -std=c99 *.c && a */
#include <assert.h>
#include <limits.h>
#include <stdio.h>
#include <stdbool.h>
void T(int a, int b)
{
int result = 0;
printf("%d %d ", a, b);
if (lowestPositive(a, b, &result))
printf(": %d\n", result);
else
printf(" are not positive\n");
}
int main(int argc, char *argv[])
{
T(5, 6);
T(6, 5);
T(6, -1);
T(-1, -2);
T(INT_MIN, INT_MAX);
T(INT_MIN, INT_MIN);
T(INT_MAX, INT_MIN);
T(0, -1);
T(0, INT_MIN);
T(-1, 0);
T(INT_MIN, 0);
T(INT_MAX, 0);
T(0, INT_MAX);
T(0, 0);
return 0;
}
Output:
5 6 : 5
6 5 : 5
6 -1 : 6
-1 -2 are not positive
-2147483648 2147483647 : 2147483647
-2147483648 -2147483648 are not positive
2147483647 -2147483648 : 2147483647
0 -1 are not positive
0 -2147483648 are not positive
-1 0 are not positive
-2147483648 0 are not positive
2147483647 0 : 2147483647
0 2147483647 : 2147483647
0 0 are not positive
This will handle all possible inputs as you request.
bool lowestPositive(int a, int b, int& result)
{
if ( a < 0 and b < 0 )
return false
result = std::min<unsigned int>( a, b );
return true;
}
That being said, the signature you supply allows sneaky bugs to appear, as it is easy to ignore the return value of this function or not even remember that there is a return value that has to be checked to know if the result is correct.
You may prefer one of these alternatives that makes it harder to overlook that a success result has to be checked:
boost::optional<int> lowestPositive(int a, int b)
{
boost::optional<int> result;
if ( a >= 0 or b >= 0 )
result = std::min<unsigned int>( a, b );
return result;
}
or
void lowestPositive(int a, int b, int& result, bool &success)
{
success = ( a >= 0 or b >= 0 )
if ( success )
result = std::min<unsigned int>( a, b );
}
tons of the answers here are ignoring the fact that zero isn't positive :)
with tricky casting and tern:
bool leastPositive(int a, int b, int& result) {
result = ((unsigned) a < (unsigned) b) ? a : b;
return result > 0;
}
less cute:
bool leastPositive(int a, int b, int& result) {
if(a > 0 && b > 0)
result = a < b ? a : b;
else
result = a > b ? a : b:
return result > 0;
}
I suggest you refactor the function into simpler functions. Furthermore, this allows your compiler to better enforce expected input data.
unsigned int minUnsigned( unsigned int a, unsigned int b )
{
return ( a < b ) ? a : b;
}
bool lowestPositive( int a, int b, int& result )
{
if ( a < 0 && b < 0 ) // SO comments refer to the previous version that had || here
{
return false;
}
result = minUnsigned( (unsigned)a, (unsigned)b ); // negative signed integers become large unsigned values
return true;
}
This works on all three signed-integer representations allowed by ISO C:
two's complement, one's complement, and even sign/magnitude. All we care about is that any positive signed integer (MSB cleared) compares below anything with the MSB set.
This actually compiles to really nice code with clang for x86, as you can see on the Godbolt Compiler Explorer. gcc 5.3 unfortunately does a much worse job.
Hack using "magic constant" -1:
enum
{
INVALID_POSITIVE = -1
};
int lowestPositive(int a, int b)
{
return (a>=0 ? ( b>=0 ? (b > a ? a : b ) : INVALID_POSITIVE ) : INVALID_POSITIVE );
}
This makes no assumptions about the numbers being positive.
Pseudocode because I have no compiler on hand:
////0 if both negative, 1 if u0 positive, 2 if u1 positive, 3 if both positive
switch((u0 > 0 ? 1 : 0) + (u1 > 0 ? 2 : 0)) {
case 0:
return false; //Note that this leaves the result value undef.
case 1:
result = u0;
return true;
case 2:
result = u1;
return true;
case 3:
result = (u0 < u1 ? u0 : u1);
return true;
default: //undefined and probably impossible condition
return false;
}
This is compact without a lot of if statements, but relies on the ternary " ? : " operator, which is just a compact if, then, else statement. "(true ? "yes" : "no")" returns "yes", "(false ? "yes" : "no") returns "no".
In a normal switch statement after every case you should have a break;, to exit the switch. In this case we have a return statement, so we're exiting the entire function.
With all due respect, your problem may be that the English phrase used to describe the problem really does hide some complexity (or at least some unresolved questions). In my experience, this is a common source of bugs and/or unfulfilled expectations in the "real world" as well. Here are some of the issues I observed:
Some programmers use a naming
convention in which a leading u
implies unsigned, but you didn't
state explicitly whether your
"numbers" are unsigned or signed
(or, for that matter, whether they
are even supposed to be integral!)
I suspect that all of us who read it
assumed that if one argument is
positive and the other is not, then
the (only) positive argument value
is the correct response, but that is
not explicitly stated.
The description also doesn't define
the required behavior if both values
are non-positive.
Finally, some of the responses
offered prior to this post seem to
imply that the responder thought
(mistakenly) that 0 is positive! A
more specific requirements statement
might help prevent any
misunderstanding (or make it clear
that the issue of zero hadn't been
thought out completely when the
requirement was written).
I'm not trying to be overly critical; I'm just suggesting that a more precisely-written requirement will probably help, and will probably also make it clear whether some of the complexity you're concerned about in the implementation is really implicit in the nature of the problem.
Three lines with the use (abuse?) of the ternary operator
int *smallest_positive(int *u1, int *u2) {
if (*u1 < 0) return *u2 >= 0 ? u2 : NULL;
if (*u2 < 0) return u1;
return *u1 < *u2 ? u1 : u2;
}
Don't know about efficiency or what to do if both u1 and u2 are negative. I opted to return NULL (which has to be checked in the caller); a return of a pointer to a static -1 might be more useful.
Edited to reflect the changes in the original question :)
bool smallest_positive(int u1, int u2, int& result) {
if (u1 < 0) {
if (u2 < 0) return false; /* result unchanged */
result = u2;
} else {
if (u2 < 0) result = u1;
else result = u1 < u2 ? u1 : u2;
}
return true;
}
uint lowestPos(uint a, uint b) { return (a < b ? a : b); }
You are looking for the smallest positive, it is be wise to accept positive values only in that case. You don't have to catch the negative values problem in your function, you should solve it at an earlier point in the caller function. For the same reason I left the boolean oit.
A precondition is that they are not equal, you would use it like this in that way:
if (a == b)
cout << "equal";
else
{
uint lowest = lowestPos(a, b);
cout << (lowest == a ? "a is lowest" : "b is lowest");
}
You can introduce const when you want to prevent changes or references if you want to change the result. Under normal conditions the computer will optimize and even inline the function.
No cleverness, reasonable clarity, works for ints and floats:
template<class T>
inline
bool LowestPositive( const T a, const T b, T* result ) {
const bool b_is_pos = b > 0;
if( a > 0 && ( !b_is_pos || a < b ) ) {
*result = a;
return true;
}
if( b_is_pos ) {
*result = b;
return true;
}
return false;
}
Note that 0 (zero) is not a positive number.
OP asks for dealing with numbers (I interpret this as ints and floats).
Only dereference result pointer if there is a positive result (performance)
Only test a and b for positiveness once (performance -- not sure if such a test is expensive?)
Note also that the accepted answer (by tvanfosson) is wrong. It fails if a is positive and b is negative (saying that "neither is positive"). (This is the only reason I add a separate answer -- I don't have reputation enough to add comments.)
My idea is based on using min and max. And categorized the result into three cases, where
min <= 0 and max <= 0
min <= 0 and max > 0
min > 0 and max > 0
The best thing is that it's not look too complicated.
Code:
bool lowestPositive(int a, int b, int& result)
{
int min = (a < b) ? a : b;
int max = (a > b) ? a : b;
bool smin = min > 0;
bool smax = max > 0;
if(!smax) return false;
if(smin) result = min;
else result = max;
return true;
}
After my first post was rejected, allow me to suggest that you are prematurely optimizing the problem and you shouldn't worry about having lots of if statements. The code you're writing naturally requires multiple 'if' statements, and whether they are expressed with the ternary if operator (A ? B : C) or classic if blocks, the execution time is the same, the compiler is going to optimize almost all of the code posted into very nearly the same logic.
Concern yourself with the readability and reliability of your code rather than trying to outwit your future self or anyone else who reads the code. Every solution posted is O(1) from what I can tell, that is, every single solution will contribute insignificantly to the performance of your code.
I would like to suggest that this post be tagged "premature optimization," the poster is not looking for elegant code.