Prayank
Prayank

Reputation: 156

Ignore zero in std::min and calculate minimum of other numbers

Minimum of non-zero numbers:

#include <iostream>
#include <algorithm>

int main() {
    
        double s1 = 1000;
        double s2 = 400;
        double s3 = 300;
        double s4 = 10;     
            
        double minimum = std::min({s1, s2, s3, s4});
        
        std::cout<<minimum<<"\n";
        
        double var = 1/minimum;
        
        std::cout<<var;
}

This works fine and returns:

10
0.1

Problem is when one of the numbers is zero:

#include <iostream>
#include <algorithm>

int main() {
    
        double s1 = 1000;
        double s2 = 400;
        double s3 = 300;
        double s4 = 0;      
            
        double minimum = std::min({s1, s2, s3, s4});
        
        std::cout<<minimum<<"\n";
        
        double var = 1/minimum;
        
        std::cout<<var;
}

It returns:

0
inf

Expected results:

300
0.00333333

How can I ignore zero from the calculation?

Upvotes: 2

Views: 1606

Answers (3)

Pepijn Kramer
Pepijn Kramer

Reputation: 13076

Or like this

#include <algorithm>
#include <limits>
#include <vector>

template<std::size_t N>
constexpr double min_no_zero(const double (&values)[N])
{
    static_assert(N>0,"There must be at least one number");
    double min = std::numeric_limits<double>::max();
    for (const auto value : values)
    {
        if ( value != 0.0 )
        {
            min = std::min(min, value);
        }
    }
    return min;
}

int main()
{
    constexpr double s1 = 1000.0;
    constexpr double s2 = 400.0;
    constexpr double s3 = 0.0;
    constexpr double s4 = 10.0;

    static_assert( min_no_zero({ s1, s2, s3, s4 }) == 10.0);
}

Upvotes: 2

Ghasem Ramezani
Ghasem Ramezani

Reputation: 2888

The std::min works as it should work if you have special requirements, you could pass a compare function with the following signature:

bool cmp(const Type1 &a, const Type2 &b);

as the second std::min function argument (the Compare template parameter):

#include <iostream>
#include <algorithm>

int main()
{
    double s1 = 1000;
    double s2 = 400;
    double s3 = 300;
    double s4 = 0;

    auto const ignore_zero = [](auto const& a, auto const& b) -> bool {
        if(0 == a)
        {
            return false;
        }
        else if(0 == b)
        {
            return true;
        }
        return a < b;
    };

    double minimum = std::min({s1, s2, s3, s4}, ignore_zero);
    std::cout << minimum << "\n";
}

But it's strange, I suggest you if you have such special requirement with your code:

  1. Try to redesign your program.
  2. Use a function/functor helper:
#include <algorithm>
#include <iostream>
#include <vector>

namespace core::helper
{
template<typename T>
struct special_find final
{
    std::vector<T> nums;
    explicit special_find(std::initializer_list<T> nums_)
        : nums(std::move(nums_))
    {
    }

    auto min() const
    {
        return *std::min_element(nums.cbegin(), nums.cend());
    }
    special_find& ignore(T const& value)
    {
        nums.erase(std::remove_if(nums.begin(), nums.end(), [&value](auto const & item)
        {
            return item == value;
        }), nums.end());
        return *this;
    }
};
} // namespace core::helper

int main()
{
    double s1 = 1000;
    double s2 = 400;
    double s3 = 300;
    double s4 = 0;

    auto const min = core::helper::special_find({s1, s2, s3, s4}).ignore(0).min();
    std::cout << min << "\n";
}

Upvotes: 1

jlanik
jlanik

Reputation: 939

Make sure that you don't pass the 0s to min. I guess that's the only general answer without knowing how your input looks like.

Upvotes: 0

Related Questions