Search code examples
c++minimumdivide-by-zero

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?


Solution

  • 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";
    }